OpenSCADで始めるプログラマブルな3Dモデリング

初投稿になります。はじめまして。 iwtn です。
今年の10月からリブセンスにJOINしました。
メンターとしてお世話になりました、そして現時点でも一緒に仕事をしている @yut_h1979 からいくらかハードルを上げられた気がしますが、今回は現時点でQiitaにタグのないようなマイナなプログラミング言語について簡単に紹介したいと思います。
恐縮ですが、仕事とはまったく関係のない話題です。

# [OpenSCAD](http://www.openscad.org/index.html)とは
簡単に言ってしまえば、3Dモデリング、モノの形を作るためのプログラミング言語です。

3Dモデリングを行う他のソフトウェアといえば、OSSではBlenderが有名です。
大抵はGUIでマウスとキーボードのショートカットを使って、3Dモデルをグリグリ操作しながら形を作っていきます。

それに対してOpenSCADは、プログラミングの基本となる動き、順次・分岐・反復と、基本的な図形、球・多面体・錐体などを組み合わせてモデリングを行っていきます。
結果的に以下のような形を**コードだけで！**作れます。
<img width="1405" alt="スクリーンショット 2015-12-20 7.45.25.png" src="https://qiita-image-store.s3.amazonaws.com/0/16864/2c21e922-b0d5-14d5-34c8-026d2c2e8043.png">
OpenSCADは、芸術的なモノではなく、どちらかと言えば工業的な製品、普段使う道具のモデリングに向いています。


このように文章で書かれても何を言っているのかわかりにくいと思います。
では、コードと一緒にどうやって3Dモデリングをしていくのか見ていきましょう。

# インストール
OpenSCADは、Windows, MacOSX, Linuxと幅広い環境で使えます。
[公式ページのダウンロード画面](http://www.openscad.org/downloads.html)にアクセスして、それぞれの環境にあったファイルをダウンロードしましょう。
MacOSXであれば、ダウンロードしたdmgファイルを開き、アプリケーションフォルダにドラッグアンドドロップするだけです。

# 画面と基本的な図形、球・多面体・錐体
<img width="1467" alt="スクリーンショット 2015-12-20 6.32.34.png" src="https://qiita-image-store.s3.amazonaws.com/0/16864/c544c5a1-624d-3022-2e29-98eaca6b6276.png">

画面は大きくコードを書く左側と3Dモデルが表示される右側に分かれます。
画面の左側に出ているコードが以下のコードになります。
このコードで作られる3Dオブジェクトは、順に（画像では左から）三角柱、円錐、球、立方体、直方体となります。

```
translate([-40, 0, 0])
cylinder(h=20, r1=8, r2=8, $fn=3);

translate([-20, 0, 0])
cylinder(h=20, r1=10, r2=0);

translate([0, 0, 10])
sphere(10);

translate([20, 0, 0])
cube(10);

translate([40, 0, 0])
cube([8, 15, 20]);

```

`translate`は、3Dオブエジェクトが生成される場所を移動させている命令です。
OpenSCADは3Dモデリングのための言語なので、当然のように空間的なベクトルを扱います。このコードでは最後の行にある`[8, 15, 20]`がXYZ軸での長さを示すベクトルを表現する値になります。

3Dモデルの表示は、画面右側の表示部分をドラッグアンドドロップやスクロールすることで操作できます。また、下部にあるメニューでも、同様の操作を行えます。ぐるぐる回転させすぎて、どういう状態がわからなくなったら、メニューの左から６番目にある「Reset View」で初期状態に表示設定を戻せます。

# 順次・分岐・反復
OpenSCADはプログラミング言語なので、変数に値を格納したり、繰り返しや分岐の処理ができます。

<img width="1405" alt="スクリーンショット 2015-12-20 6.16.20.png" src="https://qiita-image-store.s3.amazonaws.com/0/16864/116b638c-a984-1d8f-5b53-bcac6075c34e.png">

```
// x軸の間隔
x_margin = 20;

for (i = [-10:10]) {
    translate([x_margin * i, 0, 0]) {
        if (i % 2 == 0) {
            cube([10, 50, 10], center=true);
        } else {
            cube([10, 10, 50], center=true);
        }
    }
}
```
繰り返しの際の`[-10:10]`がちょっと特徴的かもしれません。これは範囲を示す値です。具体的には -10,-9,-8,...8,9,10 を表しています。
`[-10:3:10]`のように３つの値を指定した場合は、真ん中の数字はステップを表し、具体的には -10,-7,-4,...4,7,10 を表します。
<img width="1405" alt="スクリーンショット 2015-12-20 6.54.37.png" src="https://qiita-image-store.s3.amazonaws.com/0/16864/74df28e6-01c5-7130-73a9-2e1b518c466a.png">



# 図形の組み合わせ
単純な図形だけでは、現実に必要な複雑なモノのモデリングはできません。
そこでOpenSCADでは、単純な図形同士を空間的に足したり引いたりすることで複雑な形を作っていきます。
<img width="1405" alt="スクリーンショット 2015-12-20 6.16.13.png" src="https://qiita-image-store.s3.amazonaws.com/0/16864/dffd3e8b-4024-649f-9984-9b809c38faa8.png">

```
translate([-40, 0, 0])
union() {
    cube(20, center=true);
    sphere(14, center=true);
}

translate([0, 0, 0])
difference() {
    cube(20, center=true);
    sphere(14, center=true);
}

translate([40, 0, 0])
intersection() {
    cube(20, center=true);
    sphere(14, center=true);
}
```
最初の図形は、立方体と球体が単純に合わさっています。図形同士を空間的に論理演算の`OR`した結果、とでもいいましょうか。
次の真ん中の図形は、まず立方体がありそこから球体の形を抜き取っています。これを論理演算で示すのであれば（立方体 `AND` `NOT` 球体）ですね。
最後の図形は、立体同士の共通する部分のみにしています。論理演算では（立方体 `AND` 球体）とでもいえるでしょう。角がとれて柔らかい形になりました。

もちろん、一般的な3Dモデルのデータのように、頂点とそれらを結んだ面を合わせて表現することもOpenSCADでは可能ですが、基本的には、単純な図形同士を繰り返しや分岐して生成し、組み合わせることで複雑な形状を持つものを作っていきます。
身の回りの製品の形状をこういった方法で表現することを考えてみると良い頭の体操になると思います。


# マグカップを作ってみる
例えばコップは、円柱から半径の少し小さい円柱を僅かに高さを上げて引き抜けば作れる、とかですね。
それに取っ手をつければマグカップになります。
<img width="1405" alt="スクリーンショット 2015-12-20 7.30.36.png" src="https://qiita-image-store.s3.amazonaws.com/0/16864/66a64b61-cef2-b6d0-46c3-86821237df1e.png">


```
module ring(r1, r2, h) {
    difference() {
        cylinder(r = r1, h = h);
        translate([ 0, 0, -1 ]) cylinder(r = r2, h = h+2);
    }
}

module magcup(height, outer, tickness) {
    inner = outer - tickness;
    handle = height / 4;

    difference(){
        union() {
            cylinder(h=height, r1=outer, r2=outer, center=true);
            rotate([90,0,0]) {
                translate([outer, 0, -(tickness / 2)]) {
                    ring(handle, handle - tickness, tickness);
                }
            }
        };
        translate([0, 0, tickness]) {
            cylinder(h=height, r1=inner, r2=inner, center=true);
        }
    }
}

translate([100, 0, 0])
magcup(100, 40, 5);

translate([-100, 0, 0])
magcup(150, 60, 5);
```
ここではモジュールという機能を使って、同じような図形を生成する際に処理をまとめています。これで様々なサイズのマグカップを手軽に生成できます。
取っ手部分を作っている`ring`モジュールは、[ユーザーマニュアルの一部](https://en.wikibooks.org/wiki/OpenSCAD_User_Manual/Include_Statement)からお借りしました。

先に取っ手をつけておいてから内側を取り除かないと、マグカップの内側に取っ手が残ってしまうというバグ？も発生します。
このように図形同士を組み合わせる順番は大事です。
<img width="1508" alt="スクリーンショット 2015-12-20 7.26.30.png" src="https://qiita-image-store.s3.amazonaws.com/0/16864/111f1885-2065-a8b3-a503-56d8d5d78483.png">

```
module ring(r1, r2, h) {
    difference() {
        cylinder(r = r1, h = h);
        translate([ 0, 0, -1 ]) cylinder(r = r2, h = h+2);
    }
}

module magcup(height, outer, tickness) {
    inner = outer - tickness;
    handle = height / 4;

    union() {
        difference(){
            cylinder(h=height, r1=outer, r2=outer, center=true);
            
            translate([0, 0, tickness]) {
                cylinder(h=height, r1=inner, r2=inner, center=true);
            }
        };
        rotate([90,0,0]) {
            translate([outer, 0, -(tickness / 2)]) {
                ring(handle, handle - tickness, tickness);
            }
        }
    }
}

magcup(100, 40, 5);
```

その他にもOpenSCADには多彩な機能がありますが、ここでは紹介しきれません。
興味のある方は[ユーザーマニュアル](https://en.wikibooks.org/wiki/OpenSCAD_User_Manual/The_OpenSCAD_Language)を参照いただければと思います。

# STLファイルへの書き出し
画面左側の上部にメニューが有ります。
そのメニューの右の方に「Render」と「Export as STL」というボタンが有ります。
これらを順次押すと、3Dプリンタの出力サービスで使えるSTL形式でファイルに保存できます。
バグを修正し、満足のいくマグカップができたら、どこかのサービスで出力してみるのも面白いでしょう。

コードなのでバージョン管理もできます。
誰かがモデリングしたマグカップをフォークして、自分好みにカスタマイズしてもいいかもしれません！

# なぜOpenSCADなのか？
3Dプリンタも一時期の盛り上がりからだいぶ下火になったように見えます。
個人的な見解としては、3Dプリンタは既にモデリングが完了している同じ形のモノをプリントするという使い方より、より個々のリクエストに沿ったモノを作成するのに向いているのではないか、と考えています。

例えば椅子です。座りっぱなしになりやすい職業（まさにプログラマですね）では、普段使う椅子は大変重要です。そのために結構良いお値段の椅子を使っている方も多いと思います。弊社でもアーロンチェアを愛用しているプログラマは多数います。
ただ、人間工学に基づいているとはいえ、既成品でサイズも数種類しかありません。また、体の様々な状態に合わせて作られているものではありません。
そういった時に、身長、足から膝まで、膝から腰まで、骨盤の広さ、机の高さや肘など、様々なパラメータを考慮した、オーダーメイドなプロダクトを作る上で、プログラマブルなモデリングができるOpenSCADという言語に価値が見出されてくるのでは・・・？

先ほどのマグカップも人の手の大きさに合わせて作ることが可能です。お子様用に取っ手が２つ必要であれば、Z軸を中心にして180°反対側にもう一つ取っ手を追加するだけ！です。

# まとめ
プログラマブルな3DモデリングができるOpenSCADは如何でしたでしょうか？
未来はどうなるかわかりませんが、自身の実現したい世界というものを積極的に目指していけるのがエンジニアの良いところです。
「よりプログラマブルな世界」というのが自分にとっての１つの指針です。
今年もあと２週間もありませんが、来年も未来を見据えて技術を伸ばしていきたいと思っています。


# 参考

- http://www.openscad.org
- https://en.wikibooks.org/wiki/OpenSCAD_User_Manual
- https://ja.wikipedia.org/wiki/Standard_Triangulated_Language

## 続編
[OpenSCADで作る日本円硬貨選別器](http://qiita.com/ganta-viii@github/items/302cc233972f13fb57d4)