サイズが重要な場合:ARKitを使用してルーラーアプリケーションを作成する





そのため、待望のiOS 11の公式リリースの日が過ぎました。つまり、ARKit(拡張現実を備えたアプリケーションを作成するためのAppleのSDK)の知人を延期することはできません。 多くの人がこのツールの本質について聞いたことがあります。ARKitを使用すると、作成した仮想現実を周囲の現実世界にオーバーレイできます。 同時に、iPhoneまたはiPadは表示ウィンドウとして機能し、このウィンドウを使用して、何が起こっているかを観察し、その中の何かを変更できます。 さまざまなデモアプリケーションが既にインターネット上で公開されています。その助けを借りて、家具の手配、駐車場での車の駐車、周囲の空間への引き込み、他の世界への扉の作成などを行うことができます。 一言で言えば、可能性の範囲は広く、技術的な実装のみを扱う必要があります。



ARKitは、iOS 11とA9またはA10プロセッサのみを搭載したデバイスをサポートします。 したがって、アプリケーションを作成して実行するには、まずXcode 9、次にこれらのプロセッサーのいずれかとiOSの最新バージョンがインストールされたデバイスが必要です。 スタータープロジェクトは、ここからダウンロードできます



ARKitはカメラとデバイスの他のセンサーからのデータを使用して、周囲の空間のキーポイントと水平面をリアルタイムで認識します。 カッコ内では、プロセスが非常にリソースを消費することに注意してください-デバイスは熱くなります。 最初に、行をviewDidLoad()メソッドに追加します。



sceneView.debugOptions = ARSCNDebugOptions.showFeaturePoints
      
      





これにより、ARKitが見つけた重要なポイントを確認できます。 これで、アプリケーションを開始できます。しばらくすると、次の図が表示されます。



/



デバイスを空間で少し動かす必要があることに注意してください-動きの過程で、静止状態よりも多くの変化する情報がシステムに入ります。 豊富なデータは、ARKitが重要なポイントを特定するのに役立ち、その結果、さらに多くの重要なポイントがあります。



ARKitの機能を「テスト」するために、単純なラインアプリケーションを例に取り、その作成プロセス全体を実行します。 最初に、2点間の線の描画を実装してから、その長さを計算し、画面への出力を調整する必要があります。これで、プリミティブルーラーの準備が整います。 空間に線を描くために必要な変数を追加します。



 private var points: (start: SCNVector3?, end: SCNVector3?) private var line = SCNNode() private var isDrawing = false private var canPlacePoint = false
      
      





ポイントタプルには、ラインの開始ポイントと終了ポイントが含まれます。 lineはSCNNode、SceneKitシーンに追加されるオブジェクトです。isDrawingは、ポイントの選択が終了したかどうかを示す変数です。 変数canPlacePointは、それ自体を意味します。つまり、ポイントにフォーカスを合わせることができるかどうかを示します。 この場合、フォーカスは画面の中央になります。



ポイントをフォーカスできるかどうかを判断するには、ARSCNVeiwオブジェクトのhitTestメソッドを使用する必要があります。 このメソッドは、ARKitデータに基づいて、カメラからのビームと交差するすべての認識されたオブジェクトとサーフェスを検出し、デバイスから削除された順に受信した交差データを返します。



メソッドのARSCNViewDelegateで使用します

 func renderer(_ renderer: SCNSceneRenderer, updateAtTime time: TimeInterval)
      
      





リアルタイムでデータを受信します。 その結果、次のような結果が得られます。



 func renderer(_ renderer: SCNSceneRenderer, updateAtTime time: TimeInterval) { DispatchQueue.main.async { self.measure() } }   private func measure() { let hitResults = sceneView.hitTest(view.center, types: [.featurePoint]) if let hit = hitResults.first { canPlacePoint = true focus.image = UIImage(named: "focus") } else { canPlacePoint = false focus.image = UIImage(named: "focus_off") } }
      
      





このコードは、hitTestの結果をリアルタイムでチェックし、それに応じてcanPlacePoint値とフォーカスの画像(緑または赤)を設定します。 hitTestメソッドには、実装で考慮するオブジェクトを定義するオプションのリストもあります。この場合、これらは重要なポイントです。 必要に応じて、水平面を追加できます。



画面をタップすると、開始点または終了点が示されます。 画面にタパスを実装する機能で直接、変数isDrawingを変更し、新しい行を開始するたびに開始と終了の値をゼロにします。



 @objc private func tapped() { if canPlacePoint { isDrawing = !isDrawing if isDrawing { points.start = nil points.end = nil } } }
      
      





updateAtTimeデリゲート関数に戻ります。 hitTestの結果を取得して、ポイントの座標を取得し、変数の値に応じて、行の開始点または終了点を設定します。



 if isDrawing { let hitTransform = SCNMatrix4(hit.worldTransform) let hitPoint = SCNVector3Make(hitTransform.m41, hitTransform.m42, hitTransform.m43)               if points.start == nil { points.start = hitPoint } else { points.end = hitPoint } }
      
      





これで、線の始点と終点の座標が得られました-それを描くために残っています。 これを行うには、線のジオメトリを返す関数を追加します(それに応じて、SceneKitはSCNNodeを描画する方法と場所を理解します)。



 func lineFrom(vector vector1: SCNVector3, toVector vector2: SCNVector3) -> SCNGeometry { let indices: [Int32] = [0, 1]       let source = SCNGeometrySource(vertices: [vector1, vector2]) let element = SCNGeometryElement(indices: indices, primitiveType: .line)       return SCNGeometry(sources: [source], elements: [element]) }
      
      





最後に、空間に線を引くコードを追加します。



 if points.start == nil { points.start = hitPoint } else { points.end = hitPoint line.geometry = lineFrom(vector: points.start!, toVector: points.end!) if line.parent == nil { line.geometry?.firstMaterial?.diffuse.contents = UIColor.white line.geometry?.firstMaterial?.isDoubleSided = true sceneView.scene.rootNode.addChildNode(line) } }
      
      





これで、アプリケーションを起動したら、2つのポイントの間に線を引くことができます。最初のタップは開始点をマークしてフォーカスのあるポイントに線を引き始め、2番目のタップは描画モードを停止して線を修正します。 その長さを計算し、結果の値を画面に表示するためだけに残ります。











 func distance(from startPoint: SCNVector3, to endPoint: SCNVector3) -> Float { let vector = SCNVector3Make(startPoint.x - endPoint.x, startPoint.y - endPoint.y, startPoint.z - endPoint.z) let distance = sqrtf(vector.x * vector.x + vector.y * vector.y + vector.z * vector.z) return distance }
      
      





この関数は、空間内の2点間の距離を計算します。 ポイントは小さい:テキストフィールドを追加し、その中に結果を表示します。 SceneKitでは、0.01は1センチメートルに相当します。 その結果、次の結果が得られます。









アプリケーションによると、描画された線の長さは9 cmであり、実際の定規の読み取り値と非常によく相関しています。 しかし、実際には、精度はそれほど高くありません。 物体がカメラから少し離れた場所にあり、測定が表面に垂直なデバイスの位置から行われる場合に最大の精度が得られます(つまり、電話機を回転させずに表面に平行に移動する必要があります)。 水平面での測定はより正確になります。 また、カメラを遠くのオブジェクトに向けると、hitTestは無効な結果を返す場合があります-見つかったオブジェクトまでの距離は正しく決定されません。 ここでは、デュアルカメラを搭載していないiPhone 7でこれらすべてをテストしたことを予約する必要があります。 また、インターネット上のさまざまな定規のデモを見ると、ほとんどの場合、測定に同じ制限と不正確さがあります。



これが結果です。



要約すると、ARKitはゲームやエンターテイメントアプリケーションを作成するための優れたSDKであり、多くの興味深いものを思い付くことができます。 Appleの大きなメリットは、拡張現実を大衆に提供したことです。ARKitをサポートするデバイスはたくさんあり、特別なヘルメットやその他のアクセサリーを購入する必要はありません。 さらに、ARKitは、ネイティブのSpriteKit SceneKitとMetal、およびUnityとUnreal Engineの両方での作業をサポートしているため、開発が簡素化されます。



All Articles