Blender 스크립트로 분형 입체 모형 생성
본 기사의 코드는 Blender 2.79a에서 버전 확인 작업을 수행했습니다.
스크립트로 이동하는 Blender
예를 들어 Blender의 텍스트 편집기에 다음 Python 코드를 붙이고 '실행 스크립트' 를 누르면 삼각형의 평면으로 구성된 대상을 생성합니다.
import bpy
import mathutils
# 初期化
verts = [mathutils.Vector([0,0,0]),
mathutils.Vector([1,0,0]),
mathutils.Vector([0,1,0])] #頂点のリスト
fIndexes = [[0,1,2]] #面のリスト
mesh = bpy.data.meshes.new('さんかく')
mesh.from_pydata(verts,[],fIndexes) #点と面の情報からメッシュを生成
obj = bpy.data.objects.new('さんかく', mesh) #メッシュ情報を新規オブジェクトに渡す
bpy.context.scene.objects.link(obj) #オブジェクトをシーン上にリンク
obj.select = True #作ったオブジェクトを選択状態に
정점 목록 verts에는 Blender 3D 뷰의 좌표 목록이 포함되어 있습니다.Vector 객체를 사용하여 좌표를 삽입합니다.면 목록 fIndexes에는 면을 구성하는 정점 색인 목록(또는 원조)으로 구성된 목록이 나열됩니다.샘플에서verts의 0, 1, 2개의 삼각형을 만들고 싶어서 0, 1, 2로 구성된 목록은 1개로 구성된 목록을 정의했다.
이 정점 목록verts, 면 목록 fIndexes.from_pydata()에 망상물 제작 대상을 생성하는 느낌을 줍니다.
실행할 때의 인상은 바로 이렇다.
따라서 파이썬 스크립트에서 분형 그래픽을 만들 때 한 면을 이렇게 정의할 때마다 정점 목록에 좌표를 추가하여 이 점 집합에 대응하는 색인 목록을 면 목록에 추가하는 느낌으로 만든다.
이른바 분형
예컨대 그 근처에서 자라는 나무, 야채의 로망네스코처럼 그 녀석의 일부만 바라보면 그 녀석 자체의 구조가 그대로 드러나고 그 중 일부를 보면 같은 구조가 나오는데... 이런 느낌이 반복되는 걸 분형물이라고 한다.
이번에 한 것은 예에서 말한 것처럼 그렇게 복잡도가 높지 않지만 문자로만 표현하기는 어려우므로 도형을 결합시켜 제작 방법을 설명할 것이다.
삼각형으로 이루어진 분형
이번에는 정삼각형의 정점을 형성하는 데 다음과 같은 규칙을 반복해 분형을 만든다.
<생성 규칙>
정삼각형의 정점 P0, P1, P2의 경우
P3, P4, P5를 각각 P0-P1 사이, P1-P2 사이, P2-P0 사이의 중점
P6, P7, P8을 각각 P3-P4 사이, P4-P5 사이, P5-P3 사이의 중점,
P9을 P6, P7, P8과의 위치 관계로 정의하여 정사면체의 정점을 형성한다.
그림에서 보듯이 바로 이런 느낌이다.
위에 있는 그림도
한 번만 적용되는 이 규칙의 스티커는 분형할 수 없지만 이 P0에서 P9의 좌표 중에는 정삼각형을 형성하는 점도 있다.위에서 보듯이 그림의 파란색 글자에서 보듯이 원래 삼각형의 반축척 정삼각형은 3개, 6개의 축척이 더 생겼다.
이 9개의 삼각형에 대해 우리는 위에서 보여준'생성 규칙'을 차례로 정의할 것이다.
『생성 규칙』이 2단계에 적용되면 이렇게 됩니다.
9개의 삼각형 하나하나에 대해 각각 9개의 새로운 삼각형을 정의했기 때문에×9=81개의 삼각형으로 한 면을 만들었다.
이 생성 규칙을 반복하면 작은 가시가 촘촘하게 자란 분형을 만들 수 있다.
코드로 이걸 구현하면 이렇게 될 것 같은 느낌.
import bpy
import math
import mathutils
# 初期化
def normal(face): #法線ベクトル
v1 = face[1] - face[0]
v2 = face[2] - face[0]
normal = v1.cross(v2)
normal.normalize()#正規化
return normal
def tetraFractal(level, face): #level: フラクタルの複雑度 face: フラクタル生成のターゲットとなる面
if level <= 0:# 頂点と面の情報をリストに追加
global idxV
global verts
global fIndexes
verts.append(face[0])
verts.append(face[1])
verts.append(face[2])
fIndexes.append((idxV,idxV+1,idxV+2))
idxV += 3
else: # 一つ下のレベルに分解
pts = face[:] #p0~p2
pts.append((pts[0] + pts[1])/2) #p3
pts.append((pts[1] + pts[2])/2) #p4
pts.append((pts[2] + pts[0])/2) #p5
pts.append((pts[3] + pts[4])/2) #p6
pts.append((pts[4] + pts[5])/2) #p7
pts.append((pts[5] + pts[3])/2) #p8
nrm = 0.5*math.sqrt(1/6.0)*(pts[0]-pts[1]).length * normal(face)
pts.append((pts[0] + pts[1] + pts[2])/3 + nrm) #p9
level -= 1 #
tetraFractal(level,[pts[0],pts[3],pts[5]])
tetraFractal(level,[pts[1],pts[4],pts[3]])
tetraFractal(level,[pts[2],pts[5],pts[4]])
tetraFractal(level,[pts[3],pts[6],pts[8]])
tetraFractal(level,[pts[4],pts[7],pts[6]])
tetraFractal(level,[pts[5],pts[8],pts[7]])
tetraFractal(level,[pts[6],pts[9],pts[8]])
tetraFractal(level,[pts[6],pts[7],pts[9]])
tetraFractal(level,[pts[7],pts[8],pts[9]])
#
# グローバル変数定義
#
verts = [] #頂点のリスト
idxV = 0 # 頂点のインデックス番号
fIndexes = [] #面のリスト
mesh = bpy.data.meshes.new('tetraFractal') #メッシュ情報
# フラクタルを作成する起点となる三角形の頂点座標
tetraV = [mathutils.Vector([math.cos(0) , math.sin(0) , 0.0]),
mathutils.Vector([math.cos(2*math.pi/3) , math.sin(2*math.pi/3), 0.0]),
mathutils.Vector([math.cos(4*math.pi/3) , math.sin(4*math.pi/3), 0.0])
]
#
# メインルーチン
#
tetraFractal(4,tetraV)
mesh.from_pydata(verts,[],fIndexes) # 追加した点と面情報からメッシュを定義
obj = bpy.data.objects.new('tetraFractal', mesh) #メッシュ情報からオブジェクトを生成
bpy.context.scene.objects.link(obj)
obj.select = True
실행 결과:이 코드를 간으로 하는 함수인tetraFractial()을 호출하여 정점 목록과 면 목록에 분형 도형을 구성하는 정점과 면의 정보를 계속 추가합니다.첫 번째 매개 변수 level에서 위에서 보여준 생성 규칙의 횟수를 입력하고face에는 삼각형 좌표를 나타내는 Vector 대상으로 구성된 목록을 추가합니다.
tetraFractial()의else문의 블록 안의ptt[0]~pts[9]에서 상기 설명에서 말한 P0~P9에 해당하는 좌표를 계산하여 넣는다.그리고 이 pts에서 위에서 설명한 9개의 삼각형의 좌표 조합을 골라서 그 삼각형에 대해tetraFractial 자신을 각각 호출한다.호출하기 전에 level을 낮추었기 때문에 최종 level은 0이 되고, 호출은 정점과 면의 정보를 목록에 추가하는 처리가 끝납니다.
위 코드의 "#분형의 시작점으로 삼은 삼각형 정점 좌표"섹션에서 삼각형의 좌표 테트라V를 정의하고 테트라Fractial을 호출하여 이 섹션을 다음과 같이 덮어쓰고 사면체를 구성하는 4개의 삼각형을 실행합니다.
# フラクタルを作成する起点となる四面体の頂点座標
tetraV = [mathutils.Vector([math.cos(0) , math.sin(0) , 0.0]),
mathutils.Vector([math.cos(2*math.pi/3) , math.sin(2*math.pi/3), 0.0]),
mathutils.Vector([math.cos(4*math.pi/3) , math.sin(4*math.pi/3), 0.0]),
mathutils.Vector([0, 0, -1*math.sqrt(2)])
]
# tetraVからなる四面体の面情報
tetraF = [[tetraV[0],tetraV[1],tetraV[2]],
[tetraV[1],tetraV[0],tetraV[3]],
[tetraV[2],tetraV[1],tetraV[3]],
[tetraV[0],tetraV[2],tetraV[3]]]
#
# メインルーチン
#
for i in range(4):# 四面体をなす4つの三角形に対して実行
tetraFractal(4,tetraF[i])
실행 결과:손을 잡으면 굉장히 아픈 물체가 나오네요.
이 함수는 level의 값에 따라 계산량이 폭발적으로 증가하므로 주의해야 한다.현재 level은 4로 설정되어 있지만 7 정도면 자신의 환경에서 실행하는 데 2~3분 정도 걸리며 면을 만드는 수량도 보통이 아니다.규격과 메모리 용량을 상의한 후 level의 값을 설정하십시오.
보충 설명
예시 코드의 함수인tetraFractial()의 매개 변수face에서 Vector 대상은 이러한 느낌으로 가감법과 정수배를 계산할 수 있다.
만약 두 좌표 사이의 차이를 계산하고length 방법을 호출한다면 거리도 계산할 수 있다.
또한'생성 규칙'에서 P9의 좌표를 계산하기 위해서는 p0~p2로 구성된 삼각형 평면과 수직의 법선 벡터를 계산해야 하기 때문에 외적을 사용하여 정의한다.다음 섹션.
def normal(face): #法線ベクトル
v1 = face[1] - face[0]
v2 = face[2] - face[0]
normal = v1.cross(v2)
normal.normalize()#正規化
return normal
네 번째 줄의 v1.cross(v2)는 외적 v1×v2를 계산하는 중입니다.다섯 번째 줄의normalize 귀일화, 즉 길이가 1과 일치하는 것이다.
그림에서 보듯이 바로 이런 느낌이다.
이렇게 하면 법선의 벡터를 구할 수 있고 적당한 길이로 몇 배를 정한 다음에 삼각형 중앙의 좌표를 더하면 P9을 구할 수 있다.이 부분이죠?
nrm = 0.5*math.sqrt(1/6.0)*(pts[0]-pts[1]).length * normal(face)
pts.append((pts[0] + pts[1] + pts[2])/3 + nrm) #p9
참고 자료공식 참조
Math Types & Utilities (mathutils)
https://docs.blender.org/api/current/mathutils.html
분형
잡다한 과학 노트-분형의 이야기-
https://hr-inoue.net/zscience/topics/fractal/fractal.html
해설--분형ImaginaryCube--
https://www.i.h.kyoto-u.ac.jp/users/tsuiki/cfractal/kaisetu.html
Reference
이 문제에 관하여(Blender 스크립트로 분형 입체 모형 생성), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://qiita.com/hoggyson/items/99b2b669225d05990b5b텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)