見出し画像

3Dの『自車アイコン』をweb画面上で触れるようにする

こんにちは、猫パトです。
ナビタイムジャパンで『NAVITIMEドライブサポーター』や『カーナビタイム』等のサーバーサイドの開発を担当しています。

『NAVITIMEドライブサポーター』と『カーナビタイム』では地図上に表示される自位置のアイコン(以下『自車アイコン』とします)を変更することができ、ユーザーが楽しめるようにたくさんの種類の3Dの『自車アイコン』を用意しています。

画面はiOSの『ドライブサポーター』です

少し前の話になりますがAndroid、iOSの『NAVITIMEドライブサポーター』とiOSの『カーナビタイム』では『自車アイコン』を選択する画面をリニューアルし、ネイティブの画面だったものをwebviewで作り直しました。

画面のデザイン検討(事の発端)

デザイナーYさん「車をくるくるまわしたい」
猫パト「えっ、それgifでですよね?」
デザイナーYさん「いや、こう指で触れるように」
猫パト「えっっ(その発想はなかった)」
その発想はなかったのですが「さすがデザイナー視点、おもしろそうだ」と思い、どうすれば3Dをくるくる&指で触れるようになるのか調べました。
結果出来上がった画面が次の動画です。


web画面に3Dを表示するには

『NAVITIMEドライブサポーター』と『カーナビタイム』の3Dの『自車アイコン』はナビタイムジャパンのデザイナーがblenderで作成しています。
以下は、これをweb画面に表示させるための手順です。

three.jsを使ってcanvasタグにglbファイルをロードする

1.blenderで作成されたオブジェクトをglbでエクスポート
(※ハマりポイント1)(サーバーサイドエンジニアですがこのためにblenderの使い方を覚えました。お陰様で3Dオブジェクトを作れるまでになりました。)

blenderの ファイル > エクスポート > glTF2.0

2.glbファイルをサーバーに配置

3.画面側でthree.jsその他必要なライブラリ読み込み
GLTFLoaderOrbitControlsも必要)

4.画面のcanvasを用意

赤枠の部分がcanvasタグ(ロードする前は真っ白です)

5.glbファイルをcanvasにロード
※ソースはざっくりの例です。
※ハマりポイント2、3、4があります。

<script>

function loadGlb(){

// canvasタグ
const canvas = document.querySelector('#canvas');

// 画面に表示するためのレンダラー
const renderer = new THREE.WebGLRenderer({
    canvas: canvas 
});
renderer.setPixelRatio(1);
renderer.setSize(canvas.width, canvas.height);
renderer.setClearColor(0xffffff, 1.0);

// カメラ
const camera = new THREE.PerspectiveCamera(45, width / height, 1, 20000);
// ※ハマりポイント2
camera.position.set(3000, 1000, 1000);

 // コントロール
const controls = new THREE.OrbitControls(camera, renderer.domElement);
controls.autoRotate = true;  // くるくる回す

// シーンを作成
const scene = new THREE.Scene();
const loader = new THREE.GLTFLoader();

// ※ハマりポイント3
const url = 'glbファイルのURL';
let model = null;

// ロード
loader.load(
    url,
    function (glb) {
        model = glb.scene;
        model.scale.set(400.0, 400.0, 400.0);
        model.position.set(0, -400, 0);
        scene.add(model);
    },
    function (error) {
        console.log('An error happened');
        console.log(error);
    }
);
renderer.gammaOutput = true;
renderer.gammaFactor = 2.2;

// ライト
const light = new THREE.DirectionalLight(0xFFFFFF);
light.position.set(1000, 1000, 100);
scene.add(light);

// ライト追加 ※ハマりポイント4
const ambientLight = new THREE.AmbientLight(0x555555);
scene.add(ambientLight);

// 起動
tick();

function tick() {
    // リサイズ
    camera.aspect = canvas.clientWidth / canvas.clientHeight;
    camera.updateProjectionMatrix();

    controls.update();
    renderer.render(scene, camera);
    requestAnimationFrame(tick);
}

}
</script>

6.車がくるくるする
どうでしょう、動いていますね。これ指で触れます。すごいでしょう?(自画自賛)

※ハマりポイント

1.blenderにてglbでエクスポートする前に「モディファイヤー」を全て「適用」しないとglbファイルに反映されません。最初知らずにそのままエクスポートしたら色々欠けていて驚きました。

2.カメラの位置の数値(positionのx,y,z座標)は設定して実際見てみないとわからないもので、いろいろ変えて試しての繰り返しでした。ちょうどよい感じに落ち着きました。

camera.position.set(1000,1000,1000)の場合(近すぎる)
camera.position.set(3000,3000,3000)の場合(なんか遠いな)
camera.position.set(3000,1000,1000)の場合(良き)

3.glbファイルですが(管理の都合上)別のサーバーに配置したものを直接呼び出したら画面のURLとドメインが違うのでcrossエラーになりました。この場合表示されませんのでご注意ください。(ひとつプログラムを挟んで解決しました。)

4.今回はDirectionalLightAmbientLightと、2つライトを配置しました。DirectionalLightは一定の方向から照らすライト、AmbientLightは全方位から照らすライトです。DirectionalLightだけだと位置を変えてもどうしてもどこかしら影が濃くなってしまうためAmbientLightを追加しました。逆にAmbientLightだけでもイマイチでした。(ライトってこんなにあるんだ。。。と思いました。奥が深いです。)

DirectionalLightだけ(影が濃い)
AmbientLightだけ

おわりに

この記事を見て車を触りたくなった人はぜひ『NAVITIMEドライブサポーター』『カーナビタイム』(iOS)のアプリをダウンロードしてみてください。くるくるする車はまるでショールーム、実際に触ってみて地図上に表示される車の細部が実はこうなってるんだ、とわかって楽しいです。
無料で利用できるアイコンもたくさんあります。
欲しい車のデザイン(色違いもOK)のリクエストがありましたら各アプリのご意見からお寄せください。
これからも『NAVITIMEドライブサポーター』と『カーナビタイム』をよろしくお願いいたします。

『NAVITIMEドライブサポーター』はこちら
『カーナビタイム』はこちら