シン・three.jsでPlateauモデルを表示する方法
国交省による都市モデル、Plateauの3DモデルをThree.jsで表示する方法が実質ネットになかったのでまとめました
TL;DR(最初にまとめると)
- Plateauの3Dモデルは座標系が通常の3Dモデルとは異なっており、そのままだと表示されません
- Lod1と呼ばれる低解像度のモデルではテクスチャが設定されていないので、設定する必要があります
- モデル自体にも法線ベクトルが設定されておらず、そのままだと黒い塊になるので設定する必要があります
サンプルコードはどこ?
ここにあります
どうやるの?
レンダラーの初期化
このあたりは他の場合と変わりません。ここまでに限れば公式のサンプルなど参考になるリソースが大量にあるので、適当に持ってくればOKです
Plateauの座標系をなんとかする
Plateauのモデルにおいて、各頂点のz軸は通常の高さですが、x軸とy軸は平面直角座標系に基づいています。平面直角座標系は測量用の座標系であり、日本国内に複数ある基準点のいずれか一つからの距離を表しています(詳しくはこちら)。逆に言うとこのおかげでモデル上の位置を通常の緯度経度に変換するなんてこともできるのですが、一方でたいていのモデルが中心から数キロ程度離れた場所に配置されることになり、通常のモデル表示用のコードをそのまま持ってきただけでは表示されません。
そこで中心位置を何とかする必要があります。方法としてはいくつかあるのですが、threejsで表示することを考えると一番楽なのはメッシュに変換した後でそれぞれ最大値と最小値を取得、中心を計算してその分を動かすという方法になります。ただしモデルは実際には建物単位であろうと思われるサブモデルの集合体なのですが、fbx形式では親子関係がループしている場所がありその対策も必要です。
テクスチャのないモデル対策
Lod1のようにテクスチャが設定されていないモデルの場合、代替モデルを設定する必要があります。three.jsでは3Dモデルは頂点を表すgeometryとマテリアルを表すmaterialをメンバーとして有しており、テクスチャの無い場合はmaterial.mapが空になるのでこれを利用して判定します。
法線ベクトルを計算する
Plateauのモデルは3DCGやゲームでいうところのアセットよりもCAD等の設計データに近いため、光の反射等を計算するのに必要な法線ベクトルが設定されていません。先述の通りthreejsでは頂点に関わるデータはgeometryに収納されており、computeVertexNormalsメソッドにより設定できます
最終的なコード
const loader = new FBXLoader(); const lod1Example = 'models/53392546_bldg_6677.fbx'; const lod2Example = 'models/53392633_bldg_6677.fbx'; const alterMaterialColor = 0x90D7EC; loader.load(lod2Example, function (obj) { let maxX = -Infinity; let minX = Infinity; let maxY = -Infinity; let minY = Infinity; let checked = {}; function traverser(child) { if (checked[child.id] === true) { return; } child.castShadow = true; child.receiveShadow = true; checked[child.id] = true; if (child.isMesh !== true) { return child.traverse(traverser) } child.castShadow = true; child.receiveShadow = true; child.geometry.computeVertexNormals() if (!child.material.map) { child.material = new THREE.MeshToonMaterial({ color:alterMaterialColor }) } const position = child.geometry.attributes.position for (let index = 0; index < position.count; index++) { const x = position.getX(index) if (x > maxX) { maxX = x; } else if (x < minX) { minX = x } const y = position.getY(index) if (y > maxY) { maxY = y; } else if (y < minY) { minY = y } } }; obj.traverse(traverser); const centerX = (maxX + minX) / -2 const centerY = (maxY + minY) / -2; obj.position.set(centerX, centerY, 0); scene.add(obj); });
グラフを手軽に共有できるツールを作ってみました
Graphiddleという、Web上のリソースをベースにD3.js + jQueryなグラフを手軽に共有できるサービスを作ってみました。
これは何?
オープンデータやクラウド型のオフィスソフトのデータを手軽にグラフ化して共有すること、そしてグラフを手軽に使いまわすこと、その二つを目標としたWEBアプリです
例えばオープンデータプラットフォームで公開されている福井県鯖江市の男女年齢別の人口統計をベースに五才ごとにまとめたグラフ
がこんな感じです。元になったデータはここに公開されていますが、このサイトには他にも同様のデータが公開されているのでフォーク用のページでURLを切り替えれば別の町で同じようなことができます。
データ自体も男女別で2014年から2010年の分まであるので、コードをいじれば動的に切り替えたり人口ピラミッドを作ったりと色々なことができるわけです。
Study Mail開発ブログ始めました
タイトル通り、Study Mailの開発ブログ始めました。Study Mailに関する話題は今後こちらでやっていきます
東京Node学園15限目に参加してきました
「io.jsについて」
- io.jsは「friendly fork」
- 元々は「spork」。forkほど離れていないという意味
- 基本的にnode.jsとそれほど違わない
- オープンガバナンスモデルが基本
- なるべく開発者に開示
-
- 2週間に一度Googleハングアウトによるオープンミーティング
- 録画と議事録が公開される
- コアコントリビューターが一つの会社に偏らないように
- これによりコントリビューション数が増加
- コミッタも6人増加
- アクティブになった
-
- v8のバージョンはV4.1.0.14
- ecmascript6の機能が使える
- constとかテンプレートリテラル
- テストやりづらそう
- V8エンジンの動的なオプション追加
- Streamやログ出力も簡単に
- httpモジュールは古いままだが、それ以外は速くなっている。10%程
- Nodeとio.jsの混乱を日本では防ぎたい
extensible web
- これで何が変わるんだ?
- 「つべこべ言わずにコードを書け」
- 「標準化には時間がかかる」
- 「これじゃない感がある」
- 「ベンダーによって対応はまちまち」
- 「もっと開発者に力を」
- まず開発を
- そのためにはそれを実現できる低レベルな機能が必要
- ブラウザが実現する機能をもっとも単純なレベルで実現できるAPIを
- 最近ではちょっとずつ出てきている
- 実際に実装してみると大変
ws の permessage deflateを実装した話とそれによりsocket.ioがどう変わるか
CodeOnMobile
今できる通信高速化に挑戦してみた
Socket.io
- ライフゲームをみんなでプレイするゲームを実装してみた
web audio api使って声の高低に合わせてオブジェクトを上下させるアプリつくりました
13日に開催されたweb music ハッカソンで声の高低に合わせてオブジェクトを上下させるアプリ作ってきました
マイクを許可して、声か楽器の音程を上下させると丸い球が上下に動きますので、横から飛んでくる棒を避けてください。
仕組み
web audio apiには波形をフーリエ解析するAPIがあり、音にどの周波数がどれくらいの音量で含まれているのかを2行ほどで解析してくれます。(サンプル)。
これを使うことでボコーダーやコード進行の検出のような踏み込んだ音のハックができるわけです。
このアプリではanimationframeごとにもっとも音量の大きい周波数を取得し、それを音の高低としています。ただし実際には最大の周波数はかなり揺れるので50フレーム分の平均を取って平滑化し、滑らかにみせています。慣性のような挙動をするのはそのせいですね
これから
当たった時の演出を乗せて、教育用のゲームとして発展させていければな、と