TOPIC 13|VRワールドをつくるためのプラットフォームでの利用 [1/3]|Unityを使ったVRデータの作成
各種VRプラットフォームはUnity用のSDKを提供しており、Unityで制作したモデルをシーンに配置できます。VRワールドを作る準備として、UnityにPLATEAUの3D都市モデルを読み込み、見た目を整えてVR用のデータを作成します。
TOPIC13 VRワールドをつくるためのプラットフォームでの利用
PLATEAUの3D都市モデルは、VRの世界でも使えます。このトピックでは、いくつかのVRプラットフォームで、VRワールドをつくるための方法を説明します。
【目次】
13.1 VR用のデータを作る
13.1.1 OBJ形式ファイルの準備と原点の変更
13.1.2 Unityにインポートする
13.1.3 シーンへの配置と見た目の確認
13.1.4 地形のオルソ画像を貼り付ける
13.1 _ VR用のデータを作る
さまざまなVRプラットフォームがありますが、その多くは、UnityのSDKを提供しています。そこで、PLATEAUのデータを、まずはUnityに取り込み、Unity上でVR用のデータを作成する準備をします。
13.1.1 _ OBJ形式ファイルの準備と原点の変更
このトピックでは、OBJ形式のファイルを使って、VRワールドを作ります。
■ OBJ形式の3D都市モデルを準備する
次のいずれかの方法で、OBJ形式の3D都市モデルを準備します。
----------------
①G空間情報センターから、利用したい3D都市モデルのOBJ形式ファイルをダウンロードする
G空間情報センターでは、一部の都市で、CityGML形式以外に、OBJ形式やFBX形式に変換したファイルを提供しています。
2022年11月現在、提供されている都市は、下記のとおりです。
②PLATEAU SDK【TOPIC 17】やFME Form【TOPIC 4】などを使って、CityGMLから変換する
CityGMLから変換する工程を工夫することで、必要な建築物だけを取り出すなどのカスタマイズが可能です。
----------------
ここでは①の方法で、東京都23区の3D都市モデルをダウンロードしたものを使います。
G空間情報センターの東京都23区の3D都市モデルのページを開き、[OBJ]の部分からダウンロードします(図13-1)。
【メモ】
OBJ形式を利用する理由は、FBX形式に比べて軽量なだけでなく、テキストとして座標が書かれているため、プログラムでの座標計算が簡単であるためです。
【3D都市モデル(Project PLATEAU)東京都23区】
https://www.geospatial.jp/ckan/dataset/plateau-tokyo23ku
以下では例として、東京駅を含む3次メッシュ「53394661」を中心とした、下記の9区画分のデータを使います。
・53394620~53394622
・53394610~53394612
・53394600~53394602
扱うのは「LOD2の建築物」「橋梁」「地形」の3種類とします。具体的なファイルを表13-1に示します。
【メモ】
道路も同様に扱えますが、道路は2次メッシュでの分割で、切り出しが煩雑になるので、本チュートリアルでは割愛します。
種別 | ファイル名 |
---|---|
建築物 | bldg/lod2/53394620_bldg_6677_obj |
建築物 | bldg/lod2/53394621_bldg_6677_obj |
建築物 | bldg/lod2/53394622_bldg_6677_obj |
建築物 | bldg/lod2/53394610_bldg_6677_obj |
建築物 | bldg/lod2/53394611_bldg_6677_obj |
建築物 | bldg/lod2/53394612_bldg_6677_obj |
建築物 | bldg/lod2/53394600_bldg_6677_obj |
建築物 | bldg/lod2/53394601_bldg_6677_obj |
建築物 | bldg/lod2/53394602_bldg_6677_obj |
橋梁 | brid/53394620_brid_6677_obj |
橋梁 | brid/53394621_brid_6677_obj |
橋梁 | brid/53394622_brid_6677_obj |
橋梁 | brid/53394610_brid_6677_obj |
橋梁 | brid/53394611_brid_6677_obj |
橋梁 | brid/53394612_brid_6677_obj |
橋梁 | brid/53394600_brid_6677_obj |
橋梁 | brid/53394601_brid_6677_obj |
橋梁 | brid/53394602_brid_6677_obj |
地形 | dem/53394620_dem_6677.obj |
地形 | dem/53394621_dem_6677.obj |
地形 | dem/53394622_dem_6677.obj |
地形 | dem/53394610_dem_6677.obj |
地形 | dem/53394611_dem_6677.obj |
地形 | dem/53394612_dem_6677.obj |
地形 | dem/53394600_dem_6677.obj |
地形 | dem/53394601_dem_6677.obj |
地形 | dem/53394602_dem_6677.obj |
■ 原点を変更する
これら9×3種=27個のファイルについて、扱いやすいように、全体の中心付近が原点になるように移動しておきます。ここでは東京駅に近い、緯度35度40分45秒、経度139度46分08秒55のあたり、平面直角座標の9系で言うと、(-35592, -5819)のあたりを中心として扱うことにします。
表13-1に示したすべてのOBJ形式ファイルに対して、この座標を減算して、その点を原点に設定します。
例えば、「12.2 glTF形式に変換する」で説明したように、Blenderで開いて原点を調整する方法もありますが、27個のファイルがあり手間もかかるため、ここでは、Pythonで処理する方法を紹介します。
[1]OBJ形式ファイルをひとつのフォルダにまとめておく
表13-1に示したOBJ形式ファイルを、ひとつのフォルダにまとめておきます。座標変換にはテクスチャのファイルは必要ありませんが、次節においてUnityで読み込むときに必要になるので、次のように、テクスチャも併せてコピーしておきます。
├─53394600_dem_6677.obj
├─53394601_dem_6677.obj
├─53394602_dem_6677.obj
├─53394610_dem_6677.obj
├─53394611_dem_6677.obj
├─53394612_dem_6677.obj
├─53394620_dem_6677.obj
├─53394621_dem_6677.obj
├─53394622_dem_6677.obj
│
├─53394600_bldg_6677_obj
│ │ 53394600_bldg_6677.obj
│ │ materials.mtl
│ │
│ └─materials_textures
│ tbfe02919.jpg
│ tbfe03724.jpg
│ ・・・略・・・
├─53394600_brid_6677_obj
│ │ 53394600_brid_6677.obj
│ │ materials.mtl
│ │
│ └─materials_textures
│ tbfe02925.png
│ tbfe02926.png
│ ・・・略・・・
│ ・・・(以下ファイル名略)・・・
├─53394601_bldg_6677_obj
│ └─materials_textures
├─53394601_brid_6677_obj
│ └─materials_textures
├─53394602_bldg_6677_obj
│ └─materials_textures
├─53394602_brid_6677_obj
│ └─materials_textures
├─53394610_bldg_6677_obj
│ └─materials_textures
├─53394610_brid_6677_obj
│ └─materials_textures
├─53394611_bldg_6677_obj
│ └─materials_textures
├─53394611_brid_6677_obj
│ └─materials_textures
├─53394612_bldg_6677_obj
│ └─materials_textures
├─53394612_brid_6677_obj
│ └─materials_textures
├─53394620_bldg_6677_obj
│ └─materials_textures
├─53394620_brid_6677_obj
│ └─materials_textures
├─53394621_bldg_6677_obj
│ └─materials_textures
├─53394621_brid_6677_obj
│ └─materials_textures
├─53394622_bldg_6677_obj
│ └─materials_textures
└─53394622_brid_6677_obj
└─materials_textures
[2]座標を変換する
OBJ形式ファイルには、点とその結合の情報などが格納されています。点の座標情報は「v」から始まり「X座標」「Y座標」「Z座標」が空白区切りで並んだ、次の構造をしています。
【メモ】
「#」から始まる行は、コメントです。
# Created with FME Version: FME(R) 2020.2.0.0 20201027 - Build 20787 - WIN64
# COORDINATE_SYSTEM: OGC_DEF PROJCS["JGD2011 / Japan Plane Rectangular CS IX",GEOGCS["JGD2011",DATUM["Japanese_Geodetic_Datum_2011",SPHEROID["GRS 1980",6378137,298.257222101,AUTHORITY["EPSG","7019"]],AUTHORITY["EPSG","1128"]],PRIMEM["Greenwich",0,AUTHORITY["EPSG","8901"]],UNIT["degree",0.0174532925199433,AUTHORITY["EPSG","9122"]],AUTHORITY["EPSG","6668"]],PROJECTION["Transverse_Mercator"],PARAMETER["latitude_of_origin",36],PARAMETER["central_meridian",139.833333333333],PARAMETER["scale_factor",0.9999],PARAMETER["false_easting",0],PARAMETER["false_northing",0],UNIT["metre",1,AUTHORITY["EPSG","9001"]],AUTHORITY["EPSG","6677"]]
# Number of Geometry Coordinates : 5580
# Number of Texture Coordinates : 5534
# Number of Normal Coordinates : 0
v -7544.369290 -36967.000013 4.826500
v -7531.000000 -36967.000000 4.632500
・・・略・・・
よって「v」から始まる行について、X座標とY座標から原点にしたい座標の値を減算すればよいことになります。こうした処理をするPythonプログラムの例を、リスト13-1に示します。このプログラムは、次のように実行します。
python convertobj.py 変換元フォルダ名 変換先フォルダ名 原点X座標 原点Y座標
例えばWindowsの場合、手順[1]のように配置したフォルダをドキュメントフォルダのsrcとしたとき、コマンドプロンプトから次のように実行すると、原点が (-35592, -5819)に変換されたものが、destディレクトリに格納されます。
【メモ】
ここではPythonを使った例を示していますが、awkを使って1行で処理することもできます。「ワンライナーでPLATEAUのOBJファイルをちょっと使いやすくする」を参照してください。
【メモ】
%userprofile%はユーザープロファイルのフォルダを示す環境変数です。PowerShellで実行する場合は$env:USERPROFILEと記述します。
python convertobj.py %userprofile%\Documents\src %userprofile%\Documents\dest -35592 -5819
import sys, os, glob, pathlib, shutil
args = sys.argv
if len(args) != 5:
print("引数には、「変換元フォルダ」「変換先フォルダ」「原点としたいX座標」「原点としたいY座標」を順に指定してください")
exit(1)
src = args[1]
dest = args[2]
x = float(args[3])
y = float(args[4])
if not os.path.isdir(src):
print("変換元フォルダが見つかりません")
exit(1)
if not os.path.isdir(dest):
pathlib.Path(dest).mkdir(parents=True)
elif len(os.listdir(dest)) != 0:
print("変換先フォルダが空ではありません")
exit(1)
cwd = os.getcwd()
os.chdir(src)
filelist = glob.glob('**', recursive=True)
for file in filelist:
filepath = os.path.join(dest, file)
dirname = os.path.dirname(filepath)
if not os.path.isdir(dirname):
pathlib.Path(os.path.join(dirname)).mkdir(parents=True)
if os.path.splitext(file)[1] != '.obj':
# .objではない場合はコピー
if not os.path.isdir(file):
shutil.copy(file, filepath)
else:
# .objなので座標変換
with open(os.path.join(filepath), 'w') as wf:
with open(os.path.join(file), 'r') as rf:
for line in rf:
values = line.rstrip('\r\n').split(' ')
if values[0] == 'v':
values[1] = str(float(values[1]) -y)
values[2] = str(float(values[2]) - x)
wf.write(' '.join(values) + '\n')
else:
wf.write(line)
os.chdir(cwd)
リスト13-1 原点を変更するプログラム(convertobj.py)
13.1.2 _ Unityにインポートする
Unityで新しいプロジェクトを作成し、上記で原点を変更したOBJファイル群をインポートします(プロジェクトの種類は、「3D」とします)。
すべてのファイル(OBJだけでなく、マテリアルファイル(*.mtl)やテクスチャも含む)をプロジェクトの[Assets]フォルダにドラッグ&ドロップしてインポートし、細かい設定を調整します。設定は、すべて同じように設定するものと、ひとつずつ設定するものがあります。
■ Model、Rig、Animationの設定
[Shift]キーを押しながら、インポートしたすべてのOBJファイル群を選択し、インスペクターから、次のように「Model」「Rig」「Animation」を設定し、[Apply]をクリックします。
●Modelの設定
[Convert Units]のチェックを外して、スケールをそのまま読み込みます。[Import BlendShapes]や[Import Cameras]、[Import Lights]など必要ないもののチェックを外します。
●Rigの設定
[Rig]は[Animation Type]を[None]に設定します。
●Animationの設定
[Import Animation]のチェックを外します。
■ Materialsの設定
[Materials]は、ひとつずつ設定します。
●地形以外のオブジェクトの場合
地形以外(dem以外)のオブジェクトについては、[Materials]で、それぞれのOBJに、ひとつひとつ、図13-7のように設定し、[Apply]をクリックします。再ロードには、それなりに時間がかかります。
なお、図13-7の設定は、比較的管理しやすいと思われる設定です。他のやり方でも、正しくテクスチャが設定されれば問題ありません(うまくテクスチャが設定されないときは、mtlファイルやテクスチャ画像をドラッグ&ドロップし忘れていないかを確認してください)。
【メモ】
Editor拡張を使うと、すべてのOBJに同様の操作をまとめて行うことができます。量が多い場合は、Editor拡張の利用を検討するとよいでしょう。
●地形オブジェクトの場合
このチュートリアルでは、地形(dem)には、のちの手順でオルソ画像をテクスチャとして貼り込むので、地形に関しては、この段階では、[Material Creation Mode]を[None]に設定して[Apply]をクリックしておきます。
■ テクスチャの設定
テクスチャの設定も見直しておきます。のちほどモデル全体のリダクションとテクスチャの再構築をするので、ここではなるべく元のテクスチャを、そのままインポートする設定にします。
提供されているPLATEAUのOBJ形式のモデルでは、4096ピクセルの幅/高さをもつテクスチャがあるため、MaxSizeを4096にします。また、圧縮(Compression)もNoneに設定します。Mip Mapはあってもなくてもよいですが、ここでは[Generate Mip Maps]のチェックは、外しておきます。
13.1.3 _ シーンへの配置と見た目の確認
ここまで調整したOBJデータをシーンにドラッグ&ドロップして配置します。
配置する際は、空のGameObject(図13-11に示すとおり、ここでは「Root」という名前を付けましたが、任意の名称でかまいません)を作成し、その子要素として追加します。追加したGameObjectは、原点に配置するものとします。
配置すると、このように縦向きになるので、TransformでX軸方向に-90度回転します。これで正しく表示されます。
この段階では、十分なFPS(Frames Per Second)が出ていませんが、それについては、のちに軽量化することで解決していきます。
13.1.4 _ 地形のオルソ画像を貼り付ける
よりリアルな見栄えにするため、地面には、航空写真のオルソ画像を貼り付けてみます。
■ オルソ画像の入手
オルソ画像は、GeoTIFF形式で提供されています。G空間情報センターからダウンロードできます。
【3D都市モデル(Project PLATEAU)東京都23区】
https://www.geospatial.jp/ckan/dataset/plateau-tokyo23ku
■ オルソ画像の切り出し
図13-2に示した、本チュートリアルで扱うエリアは、3次メッシュで区切った9つぶんの領域です。GeoTIFF形式のオルソ画像は、2次メッシュで分割されています。そこで、必要な部分だけを切り出します。切り出しには、QGISを使います。(QGISのインストールと基本操作は【GISで活用する】を参照)
[1]地域メッシュのShapeファイルをダウンロードする
切り出しのためのマスクとするため、3次メッシュのShapeファイルをダウンロードします。G空間情報センターの下記のURLからダウンロードできます。
【全国標準地域メッシュ3次メッシュ(約1km四方)】
https://www.geospatial.jp/ckan/dataset/biodic-mesh/resource/38bd3651-120e-480f-99cf-7bb89cad7a05
[2]QGISでオルソ画像のレイヤを追加する
QGISを起動し、[レイヤ]メニューの[レイヤを追加]から[ラスタレイヤを追加]を選択して、ラスタレイヤを追加します。ここでは、図13-2に示した地域を含む「533946.tif」を追加します。
[3]地域メッシュを追加する
読み込んだオルソ画像の上に、地域メッシュのデータを重ねます。[レイヤ]―[レイヤを追加]―[ベクタレイヤを追加]を選択し、ダウンロードしておいた地域メッシュのShapeファイルを追加します。
[4]色の濃度を調整する
オルソ画像の上に、地域メッシュが重なります。上に重なっていてわかりにくいので、半透明とし、メッシュ番号が書かれたラベルを表示するようにします。
そのためには、左下のレイヤペインからmesh1をダブルクリックしてプロパティを開きます。
まずは[シンポロジ]タブで、塗りつぶしの[不透明度]を調整します。ここでは80.0%にしました。
次に、[ラベル]タブを開き、一番上のドロップダウンリストで[単一定義(single)]を選択します。
すると、[値(Value)]の設定ができるようになるので、[Name]を選択し、[OK]をクリックします。
以上の設定で、オルソ画像の上に、3次メッシュの番号が表示されるようになります。
[5]メッシュごとに画像を切り出す
ここから3次メッシュごとに、オルソ画像を切り出します。
[プロセシング]メニューから[ツールボックス]を選択し、プロセシングツールを開きます。[GDAL]の配下の[ラスタ抽出]―[マスクレイヤで切り抜く]をダブルクリックして開きます。
[マスクレイヤを切り抜く]ダイアログで、[入力レイヤ]に読み込んだオルソ画像のレイヤ(533946)を選択し、[マスクレイヤ]に[mesh1]を選択して、[選択した地物のみ]にチェックを付けます。
ダイアログを開いた状態で、ツールバーの[シングルクリックで地物選択]ボタンを選択して、切り出したい3次メッシュをクリックして選択します。例えば、「53394620」の部分をクリックします。すると色が変わります。
この状態で[実行]ボタンをクリックします。
[6]エクスポートする
すると分割した部分が切り出され、別のレイヤ(出力ファイル)が作成されるので、右クリックして[エクスポート]―[名前を付けて保存]を選び、エクスポートします。
まず、GeoTIFF形式として出力し、その後、GIMPなどの画像ソフトを使って、PNG形式など、Unityで扱いやすい形式に変換してください。
[7]必要なだけ繰り返す
[5][6]の手順を、必要なだけ(今回は図13-2に示したように9区画なのであと8回)繰り返して、それぞれの3次メッシュに相当するPNG形式ファイルを作ります。
■ 地形へのテクスチャの貼り付け
Unityの作業に戻り、地面のオブジェクトに対して、切り出したPNG形式ファイルをテクスチャとして貼りつけます。
[1]Unityにインポートする
切り出したPNG形式ファイルをプロジェクトの[Assets]フォルダにドラッグ&ドロップして、テクスチャとしてインポートします。
[2]テクスチャの設定をする
読み込んだテクスチャの[Inspector]を開き、図13-9と同様の設定をします。ただし、[Non Power of 2]の項目は、例えば、「ToLarger」など、適切なものに設定します。また、圧縮の設定なども調整するとよいでしょう。
[3]地形のマテリアルを作成する
[Assets]メニューから[Create]―[Material]を選択して、マテリアルを作成します。
作成したマテリアルの[Shader]を[Unlit/Texture]に変更します。マテリアルを作成したら、地形オブジェクト(dem)の[Inspector]を開き、[Materials]の部分に適用します。
[4]マテリアルにテクスチャを設定する
[3]のマテリアルの[Inspector]を開き、[Base (RGB)]の画像の部分に[2]のテクスチャをドラッグ&ドロップします。
【メモ】
地形の3Dモデルに用いているShaderを変えると、ここでテクスチャ画像を設定する項目が変わります。使うShaderによって適切な項目に設定してください。
【文】
大澤文孝
【監修】
常名 隆司(ユニティ・テクノロジーズ・ジャパン株式会社)
於保 俊(株式会社ホロラボ)