さて、XY座標を変えると地図を移動することができるのはお試しいただけたと思いますが、Z軸を変えても地図が拡大・縮小されないことにお気づきでしょうか。地図アプリであれば、ピンチ操作でZ軸を操作して地図を拡大・縮小するのが標準的ですが、現状のサンプルでは、Z軸の値を変えても地図が変化しないことが確認いただけると思います。これは、並行投影を使っているためです。平行投影は、オブジェクトがどの位置にあっても大きさが変化しない投影のため、Z軸を変化させても北海道の大きさが変化しません。では、拡大・縮小ができるように投影方法を変えてみましょう。
public void onSurfaceChanged(GL10 arg0, int width, int height) { //ビューポートの設定します。 GLES20.glViewport(0,0,width,height); float fov = 45.0f; //画角 float raito = (float) width/height; //画面の縦横比 float near = 1.0f; //視点から近平面までの距離 float far = 100000000.0f; //視点から遠平面までの距離 float top = near * (float)Math.tan(Math.toRadians(fov)); //画角から近平面のTOPを求める float bottom = -top;//近平面のbottom float left = bottom * raito; //近平面のleft float right = top * raito; //近平面のright Matrix.frustumM(mProjMatrix, 0, left, right, bottom, top, near, far); GLES20.glUniformMatrix4fv(muProjMatrix, 1, false, mProjMatrix, 0); }
変更後の投影方法は、透視投影(参考:図4)です。Matrix.frustumMで設定されています。サンプルソースは、視点からの画角と画面の縦横比、近平面までの距離から値を求めています。いかがでしょうか。北海道がずいぶん小さく表示されたと思います。視点のZ軸値を変更することで、北海道が拡大・縮小されますのでお試しください。構成するデータの座標値が大きいため、視点やfarの数字が巨大になっているのは愛敬ということで。
さて、ここで地図の拡大・縮小についてもう少し掘り下げて説明させていただきます。地図エンジンの挙動としては、視点を操作することで地図の拡大・縮小が行われることを理解いただけたと思いますが、Android版Yahoo!地図アプリでは、地図の拡大・縮小に伴って、地図上に表示されるデータの密度が変わります。Android版Yahoo!地図アプリをお試しいただくと、拡大した状態ではビルや歩道の形状まで表示されますが、縮小すると道路情報が主体になってくることがお分かりいただけると思います。
これは、スケールによって最適な密度のデータを再ロードしているからです。初めに地図はXYで分割されていることを説明させていただきましたが、Z軸(スケール)によってもデータが分かれて構成されています。世界を縮小していく際に等間隔で最適な密度で投影されたデータを生成して、地図の美しさ・分かりやすさ・処理の高速化を追求しています。
Android版Yahoo!地図アプリは少し変わった視点の取り扱いを行っています。データが等間隔に最適化・投影されるということは、オブジェクトの大きさも等倍で小さくなります。例えば1/2ごとにデータを切り替えたとすると、同じ建物を示すオブジェクトは、切り替わる際に1/2の大きさでデータ内に格納しています。このように処理するメリットとしては、同じ分割範囲により多くのオブジェクトを格納していくことができる点があげられます。
一方で、単純に視点をそのままでデータを切り替えてしまうと不具合が生じてしまいます。データが1/2になる位置まで視点を引いた際に、1/2になっているデータをロードすると表示されるデータは1/4の状態です。これでは急に地図が小さくなった形で表示されて不自然なため、Android版Yahoo!地図アプリでは視点を初期化する処理を加えています。
アプリケーション全体で管理されているスケール値とデータ間で管理されている実視点のスケール値の2種類で構成されているのは、Android版Yahoo!地図アプリの特徴の一つと言えるかもしれません。
まとめ
今回は、内容が大変マニアックになってしまいましたが、興味を持っていただけましたでしょうか。指での操作部分を付けくわえたサンプルをGitHubにアップしましたので、ぜひ参考にしてください。シェーダまわりの話も付けくわえたかったのですが、内容がさらにマニアックになりそうなので次回にさせていただきたいと思います。次回はシェーダの基本部分と、それを利用した色の設定や破線などの描画を織り交ぜて説明したいと思います。
本連載をきっかけに地図アプリに興味を持ってもらえると幸いです。