Blenderで数式に基づいたオブジェクトを生成したいと思って, スクリプトを書きました.
スクリプトの結果はSurfacePlotのようになります.
次のblender-wave.pyをBlender v2.8で実行すると上の画像のオブジェクトが作成されます.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import bpy | |
import numpy as np | |
import math | |
import mathutils | |
def WaveXY(x, y, x0=0, y0=0, period=1, a=1): | |
# Cos Wave | |
r = np.sqrt((x – x0) ** 2 + (y – y0) ** 2) | |
return a * np.cos(2.0 * np.pi * r / period) | |
# 初期化 | |
cols = 101 | |
rows = 101 | |
mat = np.zeros((rows, cols)) | |
x_array = np.linspace(0, 10, num=cols) | |
y_array = np.linspace(0, 10, num=rows) | |
verts = [] | |
# Update Matrix | |
for y in range(0, rows): | |
for x in range(0, cols): | |
px = x_array[x] | |
py = y_array[y] | |
# 水面波の干渉 | |
t = 2.5 | |
mat[y, x] += WaveXY(px, py, x0=0, y0=0, period=t) | |
mat[y, x] += WaveXY(px, py, x0=10, y0=10, period=t) | |
verts.append(mathutils.Vector([px, py, mat[y, x]])) | |
fIndexes = [] # 面のリスト | |
for y in range(0, rows – 1): | |
for x in range(0, cols – 1): | |
fIndexes.append([x + y * rows, | |
x + 1 + y * rows, | |
x + 1 + (y + 1) * rows, | |
x + (y + 1) * rows]) | |
mesh = bpy.data.meshes.new('wave') | |
mesh.from_pydata(verts, [], fIndexes) # 点と面の情報からメッシュを生成 | |
obj = bpy.data.objects.new('wave', mesh) # メッシュ情報を新規オブジェクトに渡す | |
bpy.context.scene.collection.objects.link(obj) # オブジェクトをシーン上にリンク(v2.8) | |
# bpy.context.scene.objects.link(obj) #v2.7 | |
obj.select = True# 作ったオブジェクトを選択状態に |
スクリプトの実行は画像のようにScriptingレイアウトで行うのがお勧めです.
ではここからコードの解説をしていきます.
- 1–4行目
必要なパッケージをインポートしています. もし, numpyが入っていなかったらインストールしてください. 7–10行目
正弦波を書くためのWaveXY
という関数を定義しています. この関数は点(x,y)における波の高さ(z座標)を返します. (x0,y0)は波の中心,period
は波の周期,a
は波の振幅です.13–18行目
プロットに必要な変数を設定しています. 肝は行列のmat
です. この行列のサイズは’rows x cols’です. この後, このmat
に波のz座標を代入していきます.x_array
とy_array
はそれぞれx軸とy軸用の配列です. 今回は両方とも0–10の範囲で宣言しました.verts
はこの後, 頂点の位置ベクトルを格納するための配列です. なお, 行列のサイズを大きくすればより精度の高いプロットを行うことができます.21–29行目
行列mat
に波の高さを代入し,verts
に点の位置ベクトルを追加しています.mat[y,x]
に点(px,py)の波の高さを代入しています. ちなみに今回プロットしているのは正弦波の干渉縞です.31–38行目
面のリストfindexes
に面を生成する点の座標を追加しています. Blenderではverts
のインデックスを指定することで面を貼ります. 今回は, 左上, 右上, 右下, 左下の順に点のインデックスを指定して四角形メッシュを貼っています.41–47行目
verts
とfindexes
を使ってメッシュを持ったオブジェクトを作成し, シーンに追加しています. Blender v2.8以降とv2.7以前ではオブジェクトのシーンへの追加方法が異なるので注意してください. dskjalさんがその辺りを解説してくれているので, 気になる方はご参照ください.
今回のスクリプトの29行目のz座標を変更するだけでも, 様々な関数をプロットすることができます. ガウシアンやポン・デ・リングも描けるはずなので挑戦してみてください.
コメント