本日はPointCloudのJavaサンプルを見てみましょう。
Android StudioのでInport projectを選択し、java_point_cloud_exampleを選択してOKボタンをクリックします。
ファイル構成は以下のようになっています。
PointCloudActivity.java | Javaによる点群表示サンプル。メインアクティビティです。 |
PointCloudRajawaliRenderer.java | 点群データのレンダラーです。 |
TouchViewHandler.java | 標準的なパン操作とズームタッチ操作の処理を含む、VR設定のトップダウンビューと3人称ビューを追加するヘルパークラスです。 |
rajawali/FrustumAxes.java | public class FrustumAxes extends Line3D FrustumとAxesの組み合わせを表すプリミティブ(基本的なもの)。錐台(すいだい、英: Frustum)は、錐体から、頂点を共有し相似に縮小した錐体を取り除いた立体図形の事。 Axesとは軸の事。 |
rajawali/Grid.java | public class Grid extends Line3D 現在のシーンの「床」を表すRajawaliオブジェクト。 これはシーンに配置された静的グリッドで、さまざまなビューにパースペクティブを提供します。 |
rajawali/PointCloud.java | public class PointCloud extends Points 色を使用して深度センサまでの距離を示すポイントクラウドをレンダリングします。 着色は光のスペクトルに基づいています。最も近い点は赤色で、最も遠くは紫色です。 |
rajawali/Points.java | public class Points extends Object3D Rajawaliの点のプリミティブ(基本型)です。 |
それでは詳しくみていきましょう。
PointCloudActivity
onCreateでは、TangoPointCloudManagerを生成しています。また、PointCloudRajawaliRendererクラス(点群データのレンダラー)のインスタンス生成を行なっています。また、DisplayManagerを取得し、画面の回転方向をmDisplayRotationメンバ変数へ保持しています。
onStartでは、bindTangoServiceメソッド内で、Tangoサービスを通常のAndroidサービスとして初期化します。
onStopでは、OpenGLスレッドまたはUIスレッドで使用されているサービスが切断するまで同期します。Tangoコールバックスレッドでこの同じオブジェクトに対してロックしないでください。すべてのTangoコールバックコールが終了するまで、Tango.disconnectはここでブロックされます。Tangoのコールバックスレッドでこのオブジェクトをロックすると、デッドロックが発生します。
bindTangoServiceではTangoサービスを通常のAndroidサービスとして初期化します。 onPauseでmTango.disconnect()を呼び出すので、これはTango Serviceのバインドを解除するので、onResumeが呼び出されるたびに新しいTangoオブジェクトを作成する必要があります。サービスがOpenGLスレッドまたはUIスレッドで使用されているときに切断に対して同期させます。
setupTangoConfigはbindTangoService内で呼ばれるメソッドで、Tango設定オブジェクトを設定します。 この呼び出しを行う前に、mTangoオブジェクトが初期化されていることを確認してください。これはデフォルトの設定を使用して、さらに深度センサーを追加します。
startupTangoもbindTangoServiceメソッド内で呼ばれるメソッドで、Tangoサービスのコールバックリスナーを設定し、Tango接続後に必要なその他のパラメータを取得します。ポイントクラウドとTangoのイベントとポーズの更新をリッスンします。
setupRendererはonCreate時に呼ばれるメソッドで、Rajawaliサーフェイスビューとそのレンダラーを設定します。 これは、理想的にはonCreateで1回だけ呼び出されます。
setupTangoUxAndLayoutもonCreate時に呼ばれるメソッドでTangoUXの設定とそのリスナーの設定を行います。イベントは、例外条件が観測されたときに「DETECTED」とみなされ、根本原因が解決されたときに「RESOLVED」とみなされます。
画面のFirstボタンを押すとカメラが現在位置に設定されます。いわゆる一人称視点になります。
Thirdボタンを押すとカメラを現在位置に設定し、Z軸に45度回転し、更にカメラをY軸に45度回した位置に固定します。いわゆる第三者視点です。
Topボタンを押すとカメラを現在位置の上部に固定し上からの俯瞰表示にします。これらボタンの処理はTouchViewHandler内で行われます。
画面上には、getAveragedDepthメソッドで計算した平均深度とポイントクラウドの数が表示されています。
PointCloudRajawaliRenderer
ポイントクラウドのデータはXYZC形式で提供されるため、ポイントあたり4つのfloatを示します。
レンダリングされたポイントクラウドを更新します。 このためには、クラウドデータを取得した時点でポイントクラウドデータとデバイスポーズが必要です。
注:これは、OpenGLレンダリングスレッドから呼び出す必要があります。
Rajawaliは左手系を使用するため、共役四元数が必要です。(共役四元数はこちらのサイトの説明がわかりやすい)
現在のデバイスポーズに関する情報を更新します。
注:これは、OpenGLレンダリングスレッドから呼び出す必要があります。
Rajawaliは四元数に対して左手系を使用するため、共役四元数が必要です。
TouchViewHandler
標準的なパン操作とズームタッチ操作の処理を含む、VR設定のトップダウンビューと3人称ビューを追加するヘルパークラスです。
実行する
では実行してみましょう。実行すると次の画像のような点群表示が得られます。リアルタイムでかなり高速に点群表示できている事が確認できます。ただ、点群の更新はちょっと遅れるようですね。そんなに応答性が良い感じではありませんが、スマホで使うには申し分ない速度でしょう。