3D航空宇宙図鑑開発記


# 概要

「[3D Aerospace Museum(3D航空宇宙図鑑)](https://tdaspbs.com/)」というサイトを開発しています。
2022現在、まだ改善の余地が多い状態ではありますが、ゼロから始めて目指してたコンセプトはある程度形になってきているので、ここまでの開発経緯を覚書として記します。

![Videotogif (1) (1).gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2664470/bac953f3-31cf-d9af-76a5-cdd5d60f555d.gif)

## 開発開始以前(～2021年1月)

元々航空宇宙に関する情報発信みたいなものをやってみたかったのですが、やるに当たって「差別化どうする?」ということを考えたのがスタートでした。

いわゆるブログ形式とかYOUTUBEにしていくのもアリといえばアリなのですが、それだと面白さとか詳しさなど、純粋に内容の完成度のみで勝負することになり、分が悪いんじゃないかと思ったのが発端です(誰と何を戦ってんの?って話ですが・・・)。

加えてもう一点、「これやってみたら面白いかも?」ということがありました。

いわゆる3Dモデルを持ち込んでWEBサイトを作るということです。

テレビやゲーム・動画では、3Dモデルを活用したコンテンツはどんどん進歩していっていますが、WEBサイトでは3Dモデル「説明に使う」ってのはまだまだ限定的だな。という感じがしていたので、サイトを作るときにこのエッセンスを取り入れればWikipedia等とも差別化出来るなと思ったのです。

特に仕事柄3D CAD等は多少使っていたので、WEBでできるかはともかく技術的には可能だろうということで、今回手を出してみることにしました。

まずは調査ということで調べていくと、Webで使用できる3D CGの技術は実際いくつかあり、そのなかでもThree.jsというライブラリが扱いやすそうだったため、これを使用して作ってみることにしました。

https://threejs.org/

ちなみにこの時点ではWebアプリケーションの作成経験自体がほとんどありませんでした。



## 調査・PoC版試作(～2021年7月)
Three.jsで作れそうということは分かったものの、この頃はそもそもWebアプリケーションの技術があまりなかったので、技術を調査・作りたいものの要件を詰める・そもそも自分自身のトレーニングを行うなどを開始しました。

この頃をPoc期と(後から)呼んでいます。

基本構成はある程度決まっていて(というか技能的にこの辺しか知らなかった)、大きくは以下でした

バックエンド：SQL Server + ASP.NET Core
フロントエンド：Razor+Javascript

まずはローカル環境にASPのサーバーを作って、「DBに登録した3Dモデルを読みだしてWebブラウザに表示する」。というWebアプリを作るところから始めました。

そもそもWebアプリケーションに詳しくないので開発の全過程で苦戦したんですが、特別苦戦したのはフロントエンドです。
なんといってもASP.NET + Razorの世界で生きていると、Javascriptはおまけくらいの位置づけで構築していくことも(あくまで「も」)できるので、Javascriptの知識が全然なかったのです。

しかし特にthree.jsを使って3Dモデルを表示する部分はJavascriptで書くしかなかったので、Razorスクリプトの中にjavascriptを入れていくのに最初は苦労しました。

このころのthree.jsの情報源はgoogleで出てくるいくつかの[入門記事](https://ics.media/entry/14771/)と、ドットインストール(有料版)のthree.js講座でした。この頃はまだ仕様が固まる以前に、要件も固まっていない段階だったので、明確な仕様は作りながら決めている段階でした。

この頃は仕様を把握しきれていないものをとにかく動くかコピペしてみて、トライアンドエラーといえば聞こえはいいですがかなり行き当たりばったり感が強い構築でした。
とにかく構築を始めてから約3か月で、DBから読みだした3DモデルをWebに表示し、下の絵の様にWebページに作ったボタンを押すことで表示する視点を自動で切り替えるという機能が出来上がりました。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2664470/3d4f56fd-eeb4-4a90-6b8e-10acb4ddb4e2.png" width=720 />

最初期に作った、3Dの木を表示するWebアプリケーション。
「DBに格納された3Dモデル+コンテンツ用のテキストを返すバックエンド」と、「3Dモデルを表示し視点と+説明文をボタン押下に従って切り替えるフロントエンド」で構成されている。

## 公開バージョン1の開発(～2021年9月)

その時点の技術力で、大まかにどんなことが実行上可能なのかが分かったので、初期バージョンの仕様を決めて本格構築を開始しました。といってもどこかに書き出したわけではなく、あくまで頭の中で以下みたいな感じのものを念頭に進めていったという感じです。

最初の要件(今風の言い方で言うならMVP?)

- 基本的な概念は、3Dモデル+文章をメインコンテンツとした記事作成・閲覧アプリ(ちなみにこの頃の名称は3DCMS(仮)だった。)
- 記事毎に複数の「インストラクション」という単位を持ち、インストラクション毎に表示する「文書」とその時のモデルに対する「視点」を定義しする。
- インストラクション切り替えボタンを表示し、ボタンを押すとそのインストラクションに従った文書と視点を画面に表示する
- 3Dモデルはフロントエンドからアップロード可能にする
- インストラクション毎の文書と視点はフロントエンドから編集可能にする
- 認証機能を持ち、ログインしたユーザーのみ編集機能を有効にする。それ以外のユーザーは閲覧のみ可能とする。

作り始めて最初にぶつかったのが、「色付きで3Dモデルを表示できない」という問題でした。
この時点まで全然知らなかったのですが、3Dモデルというのは「形状データ」と「色や質感・テクスチャ」などのデータの種類ごとにモデルが分かれていて、表示させるにはそれらを一通り表示させる必要がある。ということでした。

試作段階の木の画像が白黒なのはそういう理由です。当時は「なんだか良く分からないけど、そのうち何とかなるでしょ」と思っていたのですが、いざ実装し始めると非常に煩雑で、Ajaxが不自由な私には非常に難関でした。(ちなみに今でも正直この辺はうまくできていません。)この辺りは読出し機能を改善するのではなく、形状データと色やテクスチャデータを一つのファイルにするglTFという形式があり、それを使えば1モデル毎に複雑なことをしなくていいと分かり、使いたいモデルをBlenderでglTFに変更することで対応しました。

モデル選びは、元々それまでにSketchfab等でCC4ライセンスで配布されている飛行機や宇宙船のモデルがあることは分かっていたので、第一弾としてはISS(国際宇宙ステーション)が題材的にも自分の知識的にもよさそうということで、これを選びました。

そのほか、記事編集機能などはマークダウンを表示するライブラリなどを使うことで第一弾ではかなり平易な作りで実装しました。

その他かなり簡易的ですが、要件にある機能を一通り作り上げ、Webに第一弾を公開したのが2021年9月です。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2664470/78514cc9-3066-1077-dffa-0785f60a55b6.png)
公開バージョン1(正確にはバージョン1風に作った現行版)

## 公開バージョン2の開発(～2021年12月)

公開バージョン1を作った後、バージョン2の開発に向けては色々なことを考えていたのですが、要件は大きくは以下でした。

- 注釈(アノテーション)機能を付ける
- 全体的にリファクタリングする


アノテーション機能とは、今回の場合は↓の絵の様にモデルに対してテキストで説明を付ける機能のことです。3D CADなんかではよく見る機能ですし、sketchfab等でも似たような機能があったので、第二弾はこれを実装していくことにしました。

アノテーション機能も作り始めると色々複雑で、単純に表示すること自体も大変でしたがそれだけではなく、インストラクションの切り替えに応じてON/OFFを切り替えるなどの機能を付けると割と要件も実装も複雑化していき、気が付けばテーブルを増やすなどDBにまで変更は及んでいきました。

この改修は案を考えてから実装までこの後結局3か月近くかかることになります。

同時にもう一つ検討したのが、全体的なリファクタリングです。
ここまでこのシステムはバージョン管理ツールのようなものをほぼ使用していませんでした。
ASPのアプリを作るときにはNugetというパッケージ管理ツールを使うのですが、javascriptのライブラリはnugetで管理するにはそんなに適していないらしいということが分かり、SPAでtypescriptでバージョン管理された状態でパッケージを管理するならnpmが有力ということが分かり、この時点では構想ではありましたがゆくゆくreact + typescriptに移行する予定があったので、バックエンドの管理はnuget・フロントエンドの管理はnode.jsという構成に寄せて行きました。

ただこの頃はまだこの辺りの環境整備に対する知識があまりなかったので、npmを入れたものの一部のパッケージはaspのプロジェクトにも残り、またthree.jsはnpmからではなく手動で取得したものをプロジェクトフォルダに展開するという、かなり環境としては望ましくない構成になっていました。

結局、このすべてのフロントエンド用のパッケージをnpmから取得できていないという問題は、ここから半年以上解消にかかりました。

最終的に、typescriptへの移行、webpackとnpmの導入までは達成できました。

![93045675882d5e2e49c07a08fe1e95066d4f9505.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2664470/f94a06a6-407b-65b8-cc35-337e9efdddd9.png)
注釈機能追加版。ボタンを押すと視点と文章が切り替わることに加えて、注釈も変化するようになった。

## 公開バージョン3の開発(～2022年3月)

ここまでの過程で何とか基本的な機能は一通りそろいました。
記事はこの時点で約10点ほど作っていたのですが、この頃から次に向かって考えていたことが、「全体的に地味」ということでした。

3Dモデル入れた理由は、確かに元々は「分かりやすくするため」ではあるんですが、やはりせっかく「図鑑」と銘打っている以上、もう少し見てて楽しい感じにしたいと思うようになりました。

具体的には、宇宙を飛んでる雰囲気を出したいと思い、背景を暗くしたり、バックに地球を表示したり、太陽を出してみたり、そういうことができないかということで、検討したのがバージョン3です。

具体的には、背景色を調整可能にする、背景に地球モデル(などいろいろな星を置けるようにしてみる)、レンズフレア機能で太陽を表現する等です。
特に宇宙船関連の記事で、宇宙にいる雰囲気を出す機能はまあまあ成功を収め、説明の分かりやすさだけでなく「見る楽しさ」のようなものもある程度表現できてきたかな。と感じました。


上：バージョン2時代の宇宙探査機カッシーニの記事。下：バージョン3時代のカッシーニの記事。
バックグラウンドを宇宙風にして、土星の絵を置く事でかなり雰囲気がそれらしくなった。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2664470/de64dd72-c216-e142-2559-488879119caa.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2664470/42d4418e-28b4-31e7-63a7-485cf7d1453b.png)


## 公開バージョン4の開発(～2022年7月)
現在公開されているのはバージョン4です。
基本的な機能は従来とあまり変わりませんが、フロントエンドをReact + react-three/fiberでSPA化しています。
そうした意図や、その際の課題などもまたいずれ書こうと思います。