見出し画像

Rhino・GHをWebブラウザ連携する話

Rhino・GHは自由にプログラムを書くことでコンピュテーショナルに検討ができてすばらしいツールですが、そこまで手が動くようになるには中々のハードルがあるのも事実です。
はじめてRhino・GHを触るとなると、ソフトのインストールやアドインのインストールもハードルとなり、検討に使うところまで行きつかないことも多いです。
そんなRhino・GHが多くの人に有効利用してもらえるためのインターフェースを考えてました。
その1つがタイトルにもあるように「Webブラウザ」です。
Rhino・GHのインターフェースを直接触ることなく、誰でも触れるWebブラウザでシミュレーションができれば・・
というアイデアにつながる基礎部分です。

React Three Fiberの実装

Node.jsのインストール

React Three Fiberの実装にはNode.jsの環境が必要になります。
Node.jsは以下からインストールができます。

Node.jsって?というWeb実装に疎い人(私)は以下を参照してみてください。

React Three Fiberの実装

事前準備としてNode.jsがインストールできたらVSCodeを使って実装していきます。
C:\Users\ユーザー名\AppData\Roamingに「npm」フォルダを用意しておき、VSCodeのターミナルから以下を実行します。

npx create-react-app ghapp --template typescript

ここでは「ghapp」というアプリ名でReactアプリケーションを作成しています。
最初、アプリ名を「GHapp」としていましたが、大文字を入れるとエラーとなりますので、注意してください。
同じ罠にハマった人、きっといるはず。

次に、アプリの階層に移動し、ローカルサーバーを立ち上げます。

cd C:\Users\ユーザー名\ghapp 
npm start

http://localhost:3000にアクセスし、以下のReactアイコンがブラウザに表示されれば成功です。

サーバーを止めるにはターミナルでCtrl+Cを実行します。

three.jsとreact three fiberのインスト-ル

ターミナルで以下を実行することでthree.jsとreact three fiberをインストールします。

npm install three@0.146 @react-three/fiber@8.9.1

次に、
C:\Users\ユーザー名\ghapp\src
にApp.jsファイルを置き、コードは以下としておきます。

import "./App.css";
import { Canvas } from "@react-three/fiber";

function App() {
  return (
    <>
      <Canvas style={{ width: "100vw", height: "100vh" }}>
        <mesh>
          <sphereGeometry />
          <meshNormalMaterial />
        </mesh>
      </Canvas>
    </>
  );
}

export default App;

ここまで準備ができたら、再度サーバーを起動します。
先ほどと少し違って、以下でサーバーを起動します。これで再度サーバーを立ち上げることなく、コードを書き換えて保存することで反映されることになります。

npm start dev

React Three Fiberでモデルを表示

Ctrl+Cでサーバーを止めておき、react-three/dreiというライブラリをインストールしていきます。
react-three/dreiのインストールにはターミナルで以下を実行します。

npm install @react-three/drei

C:\Users\ユーザー名\ghapp\public
にmodelフォルダを作成し、gltfデータを保存しておきます。(ここでは仮にaaa.gltfとしておきます)
ここで、modelフォルダに保存したデータを表示するためにApp.jsファイルを書き換えます。

import "./App.css";
import * as THREE from "three";
import { Canvas } from "@react-three/fiber";
import { OrbitControls, Stage, useGLTF } from "@react-three/drei";

const material = new THREE.MeshStandardMaterial({
  vertexColors: true,
});

function App() {
  const modelPath = "/model/aaa.gltf";
  const gltf2 = useGLTF(modelPath);
  gltf2.scene.traverse((child) => {
    if (child instanceof THREE.Mesh) {
      child.material = material;
    }
  });

  return (
    <>
      <Canvas
        style={{ width: "100vw", height: "100vh", background: "#333" }}
        camera={{
          fov: 75,
          near: 0.1,
          far: 20000,
          position: [0, 20, 30],
        }}
      >
        <OrbitControls makeDefault />
        <directionalLight intensity={1.15} />
        <axesHelper scale={200} />
        <Stage intensity={0.02} environment={"city"} adjustCamera={true}>
          <primitive object={gltf2.scene} />
        </Stage>
      </Canvas>
    </>
  );
}

export default App;

3行目の記載はWebブラウザ上でモデルを自由にグルグル動かして見るための記述です。

import { OrbitControls, useGLTF } from "@react-three/drei";

ここまででWebブラウザに表示するためのプログラムが整いました。
では、Webブラウザに表示するモデルを用意しましょう。
先ほど書いた通り、gltfデータを所定のフォルダに用意することで、そのデータを読み込み、Webブラウザに表示します。
このgltfデータはGHからRhinoを通して書き出すことが可能です。

事前にRhinoのアドイン『GLTF-BINEXPORTER』をインストールしておきます。アドインは例によってFood4Rhinoで公開されてます。

GHの『GHPython』コンポーネントで以下のように記述することでgltfデータが書き出せます。

import urllib2
import json
import rhinoscriptsyntax as rs
import Rhino
import scriptcontext as sc
sc.doc = Rhino.RhinoDoc.ActiveDoc

output_folder = "C:\\Users\\ユーザー名\\ghapp\\public\\model\\"
obj_name = "voronoiSphere"
object_file_name = "{}.gltf".format(obj_name)
file_path = output_folder + object_file_name

if baked != None:
    ids = rs.ObjectsByLayer(layer_name)
    selected_objects = rs.SelectObjects(ids)
    rs.Command("_-SaveAs {} _Enter _Enter".format(file_path))
    rs.UnselectAllObjects()
    finish_export = "finish"

GHで『Bake Objects』コンポーネントでBakeすることで先ほどのGHPythonコンポーネントがBakeを受け取り、一連の流れが実行されます。

GHPythonからはgltfデータが書き出され、App.jsファイルがWebブラウザにアップロードされます。

GHで制御したモデルをWebブラウザに表示するデモ

GHでnumスライダーの値を変えることで、立体がランダムに形状変化し、このモデルのBakeをトリガーにGHPythonからgltfデータを書き出し、これが右側に表示しているWebブラウザにアップロードされてる様子です。

外部からGHを制御する

Rhino PythonからGHを制御する

Rhinoの
ツール>PythonScript>実行
で作成しておいたPythonScriptファイルを選択して実行することでGH外からGHを制御します。

numスライダーの値をGH外から制御してみます。
まずは下順として、制御するnumスライダーを特定するためにnumスライダーのGUIDを取得します。
GUIDを取得するためのScriptをGHPythonコンポーネントで以下のように書きます。

for input_comp in ghenv.Component.Params.Input:
    for source in input_comp.Sources:
        a = str(source.InstanceGuid)

上記の取得しておいたGUIDでnumスライダーを指定し、指定したnumスライダーにセットする値をPythonScriptで記述します。

import Rhino

#GHファイルへのパス
path_gh = "C:\\Users\\ユーザー名\\005_ブラウザ連携\\005_ブラウザ連携.gh"

#GH_RhinoScriptInterface を取得
gh = Rhino.RhinoApp.GetPlugInObject("Grasshopper")

#Grasshopperを開いて表示
gh.LoadEditor()
gh.CloseAllDocuments()
gh.ShowEditor()

#ghファイルの読み込み
gh.OpenDocument(path_gh)

#numSliderコンポーネントにセット
gh.SetSliderValue("24c81f37-2f1e-4a2d-981d-19b3c2537e39", 51)

#実行
gh.RunSolver(True)
#numSliderコンポーネントにセット
gh.SetSliderValue("24c81f37-2f1e-4a2d-981d-19b3c2537e39", 51)

で、numスライダーのGUIDでの指定とセットする値を記載してます。

このPythonScriptをRhinoから実行することで以下のようにnumスライダーの値が変更されて3D形状が変化しました。

実行前:numスライダー=72
実行後:numスライダー=51

numスライダーにセットする値はPythonのモジュールを使えば、実行するたびにrandomにセットすることも簡単ですね。

import random

#numSliderにセットする値をrandomに生成する
num = random.randint(1,100)

#numSliderコンポーネントにセット
gh.SetSliderValue("24c81f37-2f1e-4a2d-981d-19b3c2537e39", num)

いつもサポートいただきありがとうございます! これからもあなたの代わりに役立つ記事を更新し続けていきます。 どうぞよろしくお願いします。