
GrasshopperのUIを考える【Processing連携編】
少し空いてしまいました。
今回は、GrasshopperのUI(特に数値制御のSlider全般の操作)をわかりやすく構築できるかどうかについて書きたいと思います。
具体的にやったことは、ProcessingとGrasshopperを連携させ、Processing側からGrasshopperをいじる、というもの。いじるといっても数値の制御だけですが。
以下の動画のモデルを作成しました。
Grasshopperはパラメトリックなモデリングを得意としますが、
複雑なモデルなどを作っていくと、そのパラメーターが多いがためにキャンバス上のどこにどんなパラメーターがあるのかがわかりずらくなってしまうときがあります。
簡単な対処法としては、そのようなパラメーター(例えばnumber slider)が配置されているGrasshopperのキャンバスの画面を名前を付けて保存することが考えられます。
①保存したい画面の状態にして
②「目」のアイコンをクリックし、適当な名前を付けて保存
③保存したViewは「目」のアイコンの右にある小さな逆三角形から呼び出せます。
ただ、この方法ではコンポーネントを移動させた場合に、それに連動して保存したViewがついては来ないので、なかなか使いずらかったりもします。
そこで、NumberSliderなど数値を変化させるコンポーネントは、まとめて別のウィンドウから操作できれば便利?なのかもしれません。
じゃあ標準搭載の「Remote Panel」を使用すればいいじゃないか!という考えもあるかと思います。とてもとてもいいことだと思います。
しかし、もう少し自由度の高いスライダー(例えばスライダーの種類や配置する場所をカスタムすること)を作るために、ここではProcessingを使用してみたいと思います。
具体的には、Processingのライブラリである「ControlP5」を用いて、Processing上で作成したスライダーの数値をいじると、それがGrasshopperにとんでRhinoのビューポートのモデルが動くというものになります。
ここで、Grasshopperのプラグインとして必要となるものは、
「gHowl」です。この中にUDP通信が可能なコンポーネントがあるので、こちらを用いてProcessingから送信したデータをGrasshopperで受信します。
では、簡単に作成したものを説明します。別にProcessingと連携させる必要はないじゃん!と思う方もいるかもしれませんが、おおめに見てやってください。
①勾玉のような形状の床をRhino上で作成
②それをZ軸側に指定の数だけ複製
③各フロアの中心を基点にフロアを回転
④回転角度は各フロアの高さに比例して回転(Remapなどを用いて)
⑤最後に柱?を指定した数で作成。
下記の画像はがGrasshopperのキャンバス画面です。
左下の四角いピンク色のグループの箇所がgHowlを使用しているコンポーネントによってProcessingから数値のデータを受信し、それぞれの数値をListItemによって分けている部分です。
また、丸いピンクの部分はProcessingで受けた数値のデータがつながっているコンポーネントです。
Processingのコードです(Processing3.5.2使用)
import netP5.*;
import oscP5.*;
import controlP5.*; //ControlP5のライブラリのインポート
ControlP5 cp5;
//Slider, Knobを宣言
Slider floor_num;
Knob rotation;
Knob divide_num;
OscP5 oscP5;
NetAddress myRemoteLocation;
void setup(){
size(600, 350);
background(0);
cp5 = new ControlP5(this); //ControlP5のインスタンスを作成
floor_num = cp5.addSlider("floor_num") //
.setRange(0, 15)
.setValue(10)
.setPosition(width/8, height/4)
.setSize(200, 30)
.setNumberOfTickMarks(16);
rotation = cp5.addKnob("knobValue1") //
.setLabel("rotation")
.setRange(0, 360)
.setValue(60)
.setPosition(width/8, height/4*2)
.setRadius(60);
divide_num = cp5.addKnob("knobValue2") //
.setLabel("divide_num")
.setRange(0, 50)
.setValue(20)
.setPosition(width/8*5, height/4*2)
.setRadius(60)
.setTickMarkLength(1)
.setNumberOfTickMarks(50)
.snapToTickMarks(true);
OscProperties oscProperties = new OscProperties();
oscProperties.setListeningPort(12001);
oscProperties.setDatagramSize(60000);
oscP5 = new OscP5(this, oscProperties);
myRemoteLocation = new NetAddress("127.0.0.1", 8000);
}
void draw() {
OscMessage myMessage = new OscMessage("/test");
float a = floor_num.getValue();
float b = rotation.getValue();
float c = divide_num.getValue();
myMessage.add(a)
.add(b)
.add(c); /* add an int to the osc message */
oscP5.send(myMessage, myRemoteLocation);
}
controlP5以外にも、
netP5, oscP5のライブラリを使用します。
すみません、ひとまずここまで。
詳しいコードの説明など、
続きはまたこちらの記事上で更新するようにします。