Blenderで星形を作る

# はじめに
　以前p5.jsのwebglでレイマーチングで星形多面体をいろいろ作っていて、これをblenderでもできないかと思い、ミラーモディファイアを使えば楽にいきそうだったので試してみました。

## 準備:鏡映面を作る
　まず、3枚の合わせ鏡を作ります。この3枚でミラーモディファイアを何回か繰り返し用いることで星形多面体を作ります。3枚の法線ベクトルはそれぞれ、

```math
e1=(1,0,0),~~e2=(0,1,0),~~e3=(-\frac{1}{2}, -\frac{\phi}{2}, \frac{\phi -1}{2}) \\[5pt]
ただし\phi =\frac{1+\sqrt{5}}{2}
```
とします。これらを法線ベクトルとする3枚の平面にそれぞれPlane1,Plane2,Plane3と名前を付けておきます。
[![鏡1.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/437349/68d9a4fd-8eec-4d5f-c149-da38563dcd58.png)
](鏡1)
斜めに傾いてるのがPlane3です。face orientationがこれらのベクトルの向きになっていることが重要です。平面を任意の方向に向かせるには、デフォルトで(0,0,1)が法線ベクトルの平面を生成した後、これと向かせたい軸の単位ベクトルを加えてできるベクトルの周りに180°回転させればいいです。つまり、

```math
  (0,0,1) + (-\frac{1}{2}, -\frac{\phi}{2}, \frac{\phi -1}{2}) = (-\frac{1}{2}, -\frac{\phi}{2}, \frac{\phi +1}{2})
```
を回転のトランスフォームに代入します。
[![鏡2.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/437349/5053e09c-d36b-5b21-21ac-539ab46cfb88.png)
](鏡2)
なお、それぞれの平面はできるだけ大きくしておきます。

## 基準点
　これらの平面2つずつの交線が合計3本あります。これらの交線上に3点pab,pbc,pcaを次のように取ります。

```math
pab=(0,0,\frac{\phi}{2}),~~pbc=(\frac{1}{2},0,\frac{\phi}{2}),~~pca=(0,\frac{\phi}{6},\frac{1+2\phi}{6}).
```
これらの3点は、正二十面体の上の3点になっていて、一つの面の6分の1の領域を占めています。これを鏡で映していくと全部で120個の部屋ができます。これら120個の部屋に配置する基本となる図形をいじることで星形を作ることができます。
[![鏡3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/437349/426d2b73-a0be-154d-8eba-7ba975055c15.png)
](鏡3)
この赤い領域が基本領域になります。

## 最初：小星形二十面体
　例として小星形二十面体を作ってみます。小星形二十面体は、

```math
　pcaを中心とし、法線ベクトルが(-\frac{1}{2},0,\frac{\phi}{2})の正規化であるような平面
```
を3枚の鏡でスライスして得られる断片を鏡で何回も映して得られます。作り方にちょっと問題があるので正規化前のベクトルで指定してあります・・Plane3のときと同じようにします。なおpab,pbc,pcaにエンプティをおいておくと3Dカーソルを動かしやすい（Shift+S!!）のでおすすめです。正規化して(0,0,1)を足します。

```math
(-\frac{1}{2},0,\frac{\phi}{2})~~\rightarrow~~(-0.52573,~ 0, ~0.85065).\\[5pt]
(0,0,1)を加えると(-0.52573,~0,~1.85065).
```
これの周りに180°回転させればいいです。
[![鏡4.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/437349/77a51519-7bbf-822e-1b04-73270b8713db.png)
](鏡4)
この断片を複製します。3枚の鏡でスライスするには順にブーリアンのDifferenceを取ればいいです。三角形にならない場合は小さいので、やや大きくしてスライス後の形が三角形となるようにします。
[![鏡5.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/437349/6b6b5f0d-a585-c516-3a69-87dbf15afae2.png)
](鏡5)
小さくなりました。

## スクリプトで鏡により複製
　ここから3枚の鏡を順繰りにミラーに設定して軸をzにして（デフォルトはxになっているのですが平面の法線ベクトルを使って鏡映をやる場合にはzにしないといけないので）、その操作を5回やるのですが、間違えやすいので面倒です。そこでスクリプトでやってしまいます。最初に断片をセレクトするのを忘れずに。

```py
import bpy

obj = bpy.ops.object # 選択されたオブジェクトを取得

obj.origin_set(type = 'ORIGIN_CURSOR', center = 'MEDIAN') # 原点を座標軸の中心に置く

mirrorNames = ['Plane1', 'Plane2', 'Plane3'] #3枚の鏡

for mirrorName in mirrorNames:
    obj.modifier_add(type='MIRROR')
    mirror = bpy.context.object.modifiers["Mirror"]
    mirror.use_axis[0] = False # デフォルトはx軸なのでz軸に変更
    mirror.use_axis[2] = True
    mirror.mirror_object = bpy.data.objects[mirrorName] # ミラーオブジェクトを設定
    obj.modifier_apply(modifier = "Mirror") # ミラーを適用
    
msh = bpy.context.object.data # 選択中のオブジェクトのメッシュを取得
for v in msh.vertices:
    v.select = True # すべての頂点を選択する。これはオブジェクトモードでないとできない仕組み。

obj.mode_set(mode = "EDIT") # 編集モードへ
bpy.ops.mesh.remove_doubles() # 重複する頂点を削除する（大量に発生するので）
obj.mode_set(mode = "OBJECT") # オブジェクトモードに戻しておく
```
具体的には次のように設定します：
[![鏡6.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/437349/4ac7ca6e-e2bb-517a-04fd-01b6cc8fd4df.png)
](鏡6)
これをPlane1,Plane2,Plane3でやって、それを計5回やります（15回ミラーを適用する・・）。非常にめんどくさいですが、スクリプトを使えばワンクリックで3回分やってくれます。だから5回クリックすれば、
[![鏡7.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/437349/ffe37541-2e5c-4d56-5b21-b43078c75bba.png)
](鏡7)
できました。
[![2021-10-23 11-09-13.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/437349/b2209cb7-29e6-9a0d-7de5-a046df31a1f7.gif)
](5クリック)
元になる平面の構成を変えれば様々な星形を作ることができます。
頂点に色を付けてみました：
[![頂点に色.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/437349/cfd689ff-061f-ad8e-622c-4b8b37f241ca.png)
](鏡EX1)

# おわりに
　星形はきれいなので作ってて楽しかったです。