STUDIO TAMA

thumbnail

投稿日:2022-11-23

【Grasshopper / Three.js】Grasshopperで作成したモデルをReact Three Fiberを使ってブラウザで表示するまで

  • #Grasshopper

  • #Three.js

  • #R3F

  • #Basic

今回は、Grasshopper で作成した Rhino を、React Three Fiber(Three.js を React を使用して実装できるライブラリ)を使って Web ブラウザで表示していきたいと思います。React Three Fiber を使用すると、Vanilla.js で実装するよりもだいぶ楽にはなります。ただし、Vanilla.js で実装できないと、かなりブラックボックスになってしまうのと、複雑なことをやろうとすると難しいことが多々出てきますのでその辺りは要注意です。ソースコードは

Github

にアップしてます。

今回表示するモデル

thumbnail
thumbnail

今回ブラウザで表示するのは、以前 Grasshopper と Monoceros というプラグインを使用して作成したモデルを使用します。作り方、ご興味あれば以下のリンクからのぞいてみてください。 こちらのデータはメッシュ化した後、join して単一メッシュにしていおります。この状態で現状 18MB あります。ブラウザに持っていくにはちょっと重たいですね。 このままではロード時間もかかってしまうので、まずはこちらのモデルを軽量化していきます。

thumbnail

【Grasshopper Tutorial】 Pipe Connection using Monoceros

GrasshopperのプラグインMonocerosを使用したモデリング

Draco 圧縮をかける

thumbnail
  • ひとまず Rhino 上でできることは限られているので、モデルを Blender に移行しましょう。Blender はオープソースですので、誰でも無料で使用することができるソフトウェアとなっております。インストールは

    からできます。

  • まずは Rhinoceros から、モデルを FBX 形式でエクスポートします。

thumbnail
  • Blender にモデルをインポートします。Rhino 上でメッシュを join したので、右上のレイヤにはオブジェクトが 1 つしか格納されていませんが、もし join してなくて大量のオブジェクトがある場合は、すべて選択し Ctrl + J でジョインすることをお勧めします。
  • Draco 圧縮という技術を使用してデータを軽量化していきます。Draco 圧縮は Google が開発した圧縮方法で、WebGL をやられている方はよく使用するかと思います。Blender では Draco 圧縮したデータをエクスポートできます。(※本来であれば、Blender Python などを使用して一括でメッシュ数を減らしたりするのですが、説明が長くなるので割愛します。もしご興味あれば、「モディファイア一括適用」などで調べてみてください。)
thumbnail
  • glb 形式でエクスポートするので、モデルを選択した状態で、ファイル ⇒Export⇒glTF2.0 を選択します。
thumbnail
  • 上画像の様に check ボックスにチェックを入れてください。
  • include は Selected Objects(選択したオブジェクトのみエクスポートする。)
  • Transform は、Three.js では上方向は Z 軸ではなく Y 軸なので、Y 軸が上方向とするためにチェックを入れます。
  • Geometry に関しては、今回はロードするだけですが、とりあえず UVs、Normals をエクスポートしときます。Material もエクスポートとしておきます。
  • Compression の欄ですが、ここにチェックを入れることで Draco 圧縮されます。もし元々データが重くなければ、ここのチェックをはずし、Draco 圧縮しない glb データをエクスポートします。
thumbnail
  • 3.4MB 弱になりました。もう少し最適化すればもう 1MB ぐらい落ちそうですが、今回はよしとしましょう。Rhno 上で 18MB からスタートし、3.4MB なので悪くないかなと思います。

React Three Fiber(アプリの立ち上げ)

thumbnail
  • React Three Fiber を実装していきます。Node.js を事前にインスト-ルしておく必要があります。こちらから LTS バージョンをインストールしておいてください。(※最新版でもいいのですが、新しすぎるとバグなど残っていることもあるので、LTS 推奨版をインストールすることをお勧めします)
  • 今回はエディターは VSCode を使用しております。プロジェクトを保存するディレクトリを開き、VSCode のターミナルから以下の 1 行目を実行し、myapp というアプリ名で React アプリケーションを作成します。少し時間がかかります。(※ちなみに React のバージョンは 18.2 です)
  • その後、2 行目の cd myapp でアプリの階層に移動します。
  • 3 行目 npm start でローカルサーバーを立ち上げます。おそらくデフォルトでは PORT:3000 で立ち上がるので、http://localhost:3000 にアクセスし、上画像の様に React のアイコンがブラウザに表示されれば OK です。
  • 問題なければ Ctrl + C でサーバーを止めましょう。
1npx create-react-app myapp
2cd myapp
3npm start
  • three.js と react three fiber をインスト-ルします。ターミナルで以下を実行してください。ちなみに今回私がインストールしたバージョンと合わせたい方は 2 行目を実行してください。
1 npm install three @react-three/fiber
2 npm install three@0.146 @react-three/fiber@8.9.1
  • App.js を以下の様に書き換えます。
1import "./App.css";
2import { Canvas } from "@react-three/fiber";
3
4function App() {
5  return (
6    <>
7      <Canvas style={{ width: "100vw", height: "100vh" }}>
8        <mesh>
9          <sphereGeometry />
10          <meshNormalMaterial />
11        </mesh>
12      </Canvas>
13    </>
14  );
15}
16
17export default App;
  • その後、サーバーを再度起動します。今度は npm start dev で起動します。これで再度サーバーを立ち上げることなく、コードを書き換えて保存すれば反映されます。
thumbnail
  • 上画像の様に、球体が表示されれば OK です。

React Three Fiber(モデルの表示)

  • それでは作成したモデルを表示していきます。まずは、react-three/drei というライブラリをインストールしていきます。こちらは、React Three Fiber の実装を簡単にしてくれるモジュールを提供してくれる便利なライブラリとなっております。⇒ドキュメント
  • Ctrl+C でサーバーを止め、(※サーバーを止めずにターミナルをもう1つ立ち上げても OK)以下を実行してインスト-ルします。
1npm install @react-three/drei
  • public ディレクトリに model ディレクトリを作成し、blender から掃き出した glb データを格納します。
  • App.js を以下の様に書き換えます。
1import "./App.css";
2import { Canvas } from "@react-three/fiber";
3import { useGLTF } from "@react-three/drei";
4
5function App() {
6  const model = useGLTF("/model/pipe.glb");
7
8  return (
9    <>
10      <Canvas style={{ width: "100vw", height: "100vh" }}>
11        <primitive object={model.scene} />
12      </Canvas>
13    </>
14  );
15}
16
17export default App;
thumbnail
  • サーバーを起動してブラウザを確認すると、上画像の様にモデルが表示されます。(※モデルのサイズによっては、カメラの位置との兼ね合いで映ってないかもですが。)
  • Vanilla.js で実装したことがある方ならわかるかと思いますが、React Three Fiber をつかうとかなり少ないコードで書けちゃいます。
  • しかし、真っ黒ですね。原因は、Material は Blender からエクスポートしたので割り当てられてはいるが、ライトがない。
  • またカメラの位置を設定していないのでモデル全体が見えてない。といった感じです。
  • とりあえずカメラの位置を調整します。カメラの座標を(0,5,10)に設定します。
  • directionalLight を設け、光を当ててあげます。また、Canvas の background を#333 と背景を暗くしています。
1import "./App.css";
2import { Canvas } from "@react-three/fiber";
3import { useGLTF } from "@react-three/drei";
4
5function App() {
6  const model = useGLTF("/model/pipe.glb");
7
8  return (
9    <>
10      <Canvas
11        style={{ width: "100vw", height: "100vh", background: "#333" }}
12        camera={{
13          fov: 75,
14          near: 0.1,
15          far: 200,
16          position: [0, 5, 10],
17        }}
18      >
19        <directionalLight position={[0, 10, 0]} intensity={1.0} />
20        <primitive object={model.scene} />
21      </Canvas>
22    </>
23  );
24}
25
26export default App;
thumbnail
  • いい感じですね。次に OrbitContorol を設け、モデルを自由に見れるようにします。
1import "./App.css";
2import { Canvas } from "@react-three/fiber";
3import { OrbitControls, useGLTF } from "@react-three/drei";
4
5function App() {
6  const model = useGLTF("/model/pipe.glb");
7
8  return (
9    <>
10      <Canvas
11        style={{ width: "100vw", height: "100vh", background: "#333" }}
12        camera={{
13          fov: 75,
14          near: 0.1,
15          far: 200,
16          position: [0, 5, 10],
17        }}
18      >
19        <directionalLight position={[0, 10, 0]} intensity={1.0} />
20        <OrbitControls makeDefault />
21        <primitive object={model.scene} />
22      </Canvas>
23    </>
24  );
25}
26
27export default App;
thumbnail
  • OrbitControls を追加しました。これで、[0,0,0]中心にカメラを動かすことができます。
  • これでモデルの表示が完了しましたが、もう少し手を加えていきます。

おまけ

thumbnail
1import "./App.css";
2import { Canvas } from "@react-three/fiber";
3import { Environment, OrbitControls, useGLTF } from "@react-three/drei";
4import * as THREE from "three";
5
6function App() {
7  const model = useGLTF("/model/pipe.glb");
8  Object.keys(model.materials).forEach((key) => {
9    const material = model.materials[key];
10    material.roughness = 1.0;
11    material.color = new THREE.Color("#008b8b");
12  });
13
14  return (
15    <>
16      <Canvas
17        style={{ width: "100vw", height: "100vh", background: "#333" }}
18        camera={{
19          fov: 75,
20          near: 0.1,
21          far: 200,
22          position: [0, 5, 10],
23        }}
24      >
25        <Environment preset="sunset" />
26        <OrbitControls makeDefault />
27        <primitive object={model.scene} />
28      </Canvas>
29    </>
30  );
31}
32
33export default App;
  • マテリアルの色を変更し、roughness もマット感のある感じにしております。
  • また、Diretional Light ではなく、drei がモジュール化している環境光に変更しました。 以上になります。今回は、React Three Fiber 使用しましたが、もちろん通常の Three.js でも同じことができます。もし Three.js に興味があれば、個人的にはThree.js journeyがおすすめです。javascript の基礎は必要ですが、Three.js の基本から、シェーダー、React three fiber までサポートされてます。Typescript のみサポートされていませんが、Typescript は別で勉強すれば全く問題ないと思います。95 ドルですが、かなりボリュームのある内容になっており、全然安いかなと個人的には思います。ご興味あればリンクから覗いてみてはいかがでしょうか。

【参考】

目 次