1. Introduction
Blender 3D Scripting : Introduction to Blender Python - 001.
1) 블렌더 v5.0 기본 환경 상태에서, <Ctrl + PgUp> 또는 <Ctrl + PgDn> 조합키를 여러번 연속으로 쳐서 <스크립트 창> 열기.
2) 오른쪽 <코드 편집창> 열기.
3) New.. 아이콘을 클릭해야 코드 입력 가능함.
4) 참고용 코드 복붙 후, 테스트!
◈ 코드 텍스트 입력을 위한 코드 에디터 창 열기 : Shift + F11
◈ 코드 텍스트 글자 크기 조절 : Ctrl + Mouse Wheel 앞 뒤로 돌리기.
2. Code 예제 - 1
# 예제 코드 1 : 3 x 3 정방형 규브 배열 생성하기
import bpy
# 기존 오브젝트 삭제 (선택 사항)
bpy.ops.object.select_all(action='SELECT')
bpy.ops.object.delete(use_global=False)
# 큐브 크기와 간격 설정
cube_size = 2
spacing = 3
# 3x3 배열 생성
for i in range(3):
for j in range(3):
# 큐브 생성
bpy.ops.mesh.primitive_cube_add(
size=cube_size,
location=(i * spacing, j * spacing, 0)
)
◈ 결과 :


3. Code 예제 - 2
# 예제 코드 2 : 3 x 3 x 3 정방형 입체 규브 배열 생성하기
import bpy
# 기존 오브젝트 삭제 (선택 사항)
bpy.ops.object.select_all(action='SELECT')
bpy.ops.object.delete(use_global=False)
# 큐브 크기와 간격 설정
cube_size = 2
spacing = 3
# 3x3x3 배열 생성
# (주석 수정 필요 ^.^;
# 안쪽부터 실행되므로.. )
for i in range(3): # X축 방향
for j in range(3): # Y축 방향
for k in range(3): # Z축 방향
bpy.ops.mesh.primitive_cube_add(
size=cube_size,
location=(i * spacing, j * spacing, k * spacing)
)
◈ 결과 :


4. Notes
◈ 블렌더에서 Python 스크립트를 사용해 3×3 정방형 배열로 큐브를 생성하려면 bpy 모듈을 활용하면 됩니다. 아래 예시는 Blender 5.0 환경에서 실행 가능한 코드입니다.
코드 설명
1) primitive_cube_add() : 큐브를 하나 새롭게 생성하는 함수입니다.
2) primitive_cube_add() 함수 앞에 붙어 있는 bpy.ops.mesh 부분은 이 함수가 소속('=.모듈)을 나타낸다고 생각할 수 있습니다.
3) size = cube_size : 큐브의 크기를 지정합니다. 단위는 블렌더에서 자체로 사용하는 고유의 '블렌더 단위'라고 할 수 있습니다.
4) location = (i * spacing, j * spacing, 0) : X, Y 좌표를 반복문으로 계산해 3×3 배열 형태로 배치합니다. Z 좌표는 편의상 0으로 고정 시켜둡니다.
5) spacing : 큐브 간격을 조절할 수 있습니다. 이렇게 하면 바닥 평면 위에 3×3 정방형 배열로 큐브가 생성됩니다.
6) 만약 3×3×3, 즉 **입체적인 배열(큐브 배열)**을 원한다면 for k in range(3):를 추가해 Z축에도 반복문을 적용하면 됩니다.
◈ 여기서는 큐브를 3×3×3 입체 배열로 생성하는 Python 코드 예시를 보여 드리겠습니다. Blender 5.0에서 실행하면 X, Y, Z 축 방향으로 각각 3개씩 3 × 3 × 3 개, 즉 총 27개의 큐브가 생성됩니다.
◈ 3중 반복문 부분 추가 설명 :
(수정 필요 ^.^; 안쪽부터 실행되므로.. )
- for i in range(3) --> X축 방향으로 3개
- for j in range(3) --> Y축 방향으로 3개
- for k in range(3) --> Z축 방향으로 3개
- 결과적으로 3 x 3 x 3 = 27개의 큐브가 격자 형태로 배치됩니다.
- spacing 값을 조절하면 큐브 간격을 넓히거나 좁힐 수 있습니다.
만약 배열 전체를 한 덩어리처럼 중앙에 배치하고 싶다면, location 계산 시 -(spacing)을 곱해 중심을 맞추는 방식도 가능합니다.
◈ 시작 지점 좌표 수정법 : 입체 도형 큐브의 시작 지점 좌표가 마음에 들지 않을 대 수정은 대략 이렇게 합니다만.
# 큐브 크기와 간격 설정
cube_size = 2
spacing = 4
# 3x3 배열 생성. 2축 체계는 그대로 살려두고, 한 축 값만 고정 시키면 될 듯. 없애도 되지만.
for i in range(12): # X축 방향
for j in range(1): # Y축 방향. Z축은 일단 제거.
bpy.ops.mesh.primitive_cube_add(
size=cube_size,
location=(j * spacing, i * spacing-((4*11)/2), 0)
)
# 완전한 코드는 3번 파일을 참고하세요. location은 x, y, z 3축 좌표값을 받는 튜플 변수.
◈ 실행결과

■ 응용 연습 과제
1) Not Yet!
2) Not Yet!
5. Update 1.
# 참신한(?) 시도를 하고 있는 YS군을 위한 객체 하나만 삭제하기 예제입니다.
# Update 1-1
import bpy
bpy.ops.object.select_all(action='SELECT')
bpy.ops.object.delete(use_global=False)
cube_size = 2
spacing = 3
for i in range(3):
for j in range(3):
bpy.ops.mesh.primitive_cube_add(size=cube_size, location=(i*spacing, j*spacing, 0)
)
obj = bpy.data.objects.get("큐브.008")
if obj:
bpy.ops.object.select_all(action='DESELECT') # 모든 선택 해제
obj.select_set(True) # 대상 선택
bpy.context.view_layer.objects.active = obj # 대상 활성화. 활성화를 해야만 삭제할 수 있음. 활성화는 하나만 가능!
bpy.ops.object.delete(use_global=False) # 활성(및 선택)된 오브젝트 삭제
else:
print("큐브.008 오브젝트를 찾을 수 없습니다.")
"""
코드 요약 해설 :
■ bpy.context.view_layer.objects.active = obj
현재 뷰 레이어에서 활성 오브젝트(Active Object)를 obj로 설정하라는 뜻입니다. Blender의 많은 bpy.ops 연산자들은 선택(selected) 뿐만 아니라 활성(active) 오브젝트를 기준으로 동작하므로, 특정 오브젝트를 연산 대상으로 삼으려면 활성으로 지정해야 합니다.
■ 핵심 개념
- 뷰 레이어 view_layer
현재 화면에 보이는 레이어(컬렉션 포함) 컨텍스트를 나타냅니다. 같은 장면(scene)이라도 여러 뷰 레이어가 있을 수 있습니다. - 활성 오브젝트 Active Object
여러 오브젝트가 선택되어 있어도 그중 하나만 활성 상태가 됩니다. 활성 오브젝트는 연산자들이 기본으로 참조하는 대상입니다. - 선택 selected vs 활성 active
- 선택: 여러 개를 동시에 선택할 수 있음 (obj.select_set(True)).
- 활성: 한 번에 하나만 존재. bpy.context.view_layer.objects.active로 접근/설정.
■ 정리 :
많은 bpy.ops 함수(예: bpy.ops.object.delete(), bpy.ops.object.origin_set() 등)는 활성 오브젝트 또는 선택된 오브젝트들을 기준으로 동작합니다. 따라서 특정 오브젝트 하나를 조작하려면:
- 해당 오브젝트를 선택하고
- 그 오브젝트를 활성으로 설정한 뒤
- 연산자 호출
이 순서를 지키면 의도한 오브젝트에 정확히 연산이 적용됩니다.
"""
# Update 1-2
# 생성되는 객체들의 이름을 사전에 지정하기.
# 객체들의 이름이 한글 이름이나 이름 때문에 에러가 생길 수도 있어서
# 객체를 생성할 때에 아예 이름을 지정해서 생성하는 방법을 보여줍니다.
# 그리고 다른 삭제법.
import bpy
# 장면 초기화
bpy.ops.object.select_all(action='SELECT')
bpy.ops.object.delete(use_global=False)
cube_size = 2
spacing = 3
# 3 x 3 큐브 생성 및 명시적 이름 지정
for i in range(3):
for j in range(3):
bpy.ops.mesh.primitive_cube_add(size=cube_size, location=(i * spacing, j * spacing, 0))
obj = bpy.context.active_object
obj.name = f"Cube_{i}_{j}"
# 예: Cube_2_2 삭제
target_name = "Cube_2_2"
obj = bpy.data.objects.get(target_name)
if obj:
bpy.data.objects.remove(obj, do_unlink=True)
else:
print(f"{target_name} 오브젝트를 찾을 수 없습니다.")
"""
코드 요약 설명 : 핵심만
■ 선택/활성 상태를 건드리지 않고 바로 삭제하려면 bpy.data.objects.remove를 사용하면 더 안전합니다.
obj = bpy.data.objects.get("Cube_1_1")
if obj:
bpy.data.objects.remove(obj, do_unlink=True)
■ 추가 팁
- 활성 설정은 뷰 레이어에 종속됩니다. 여러 뷰 레이어를 사용하는 경우 의도한 레이어의 활성 오브젝트를 설정해야 합니다.
- 스크립트 자동화에서는 가능한 한 bpy.data.objects.remove(..., do_unlink=True)처럼 연산자 의존성을 줄이는 방식이 더 안정적입니다.
■ obj.name = f"Cube_{i}_{j}"
: for 루프에 사용된 i와 j 값을 받아와서 여기에서 객체 이름에 사용합니다.
실제로는 Cube_1_1, Cube_1_2_, ... 처럼 이름이 지어집니다.
"""
■ 추가 예제 : 활성 객체를 15도 정도 Z축을 기준으로 회전시키기.
# 활성화 방법은 이전 예제를 따른다고 보고....
# 이전 예제와 비슷하게 해야함. 아래 다음 코드는 활성화 관련 일부 수정이 필요.
import bpy
import math
obj = bpy.context.active_object
if obj:
obj.rotation_mode = 'XYZ'
obj.rotation_euler[2] += math.radians(15)
else:
print("활성 오브젝트가 없습니다.")
"""
핵심 정리
- rotation_euler[2]는 Z축 회전(라디안)입니다.
- 각도는 라디안으로 지정해야 하므로 math.radians(15)를 사용하세요.
- obj.rotation_mode = 'XYZ'로 회전 모드를 명확히 해두면 예기치 않은 회전 순서 문제를 줄일 수 있습니다.
- 로컬 Z축(오브젝트 자체 기준)과 월드 Z축(씬 기준)은 다르므로 목적에 맞는 방법(Euler 변경 vs 행렬 곱)을 사용하세요.
(# 일단 이 부분은 개념 난이도 문제로 제외/보류.) - obj.rotation_mode = 'XYZ'
역할: 오브젝트의 회전 표현 방식을 Euler 각도(오일러 회전)로 설정하고, 회전 순서를 X → Y → Z로 지정합니다. Euler 모드는 오브젝트의 rotation_euler 속성과 연동됩니다. - obj.rotation_euler[2] += math.radians(15)
역할: 오브젝트의 Z축 회전(세 번째 요소)에 현재 값에 15도(라디안)를 더해 증분 회전을 적용합니다. rotation_euler[0]은 X, [1]은 Y, [2]는 Z를 의미합니다. 각도는 라디안 단위로 다뤄야 합니다. - 회전 모드를 명시해야 함 :
Blender는 회전을 Euler, Quaternion, Axis-Angle 등 여러 방식으로 내부 저장할 수 있습니다. rotation_mode가 'QUATERNION' 등으로 되어 있으면 rotation_euler를 읽거나 쓰는 동작이 기대와 다르게 동작할 수 있으므로, Euler 값을 직접 조작하려면 명확히 'XYZ' 같은 Euler 모드로 설정해야 합니다. - 로컬 Z축 vs 월드 Z축
- obj.rotation_euler를 변경하면 **오브젝트의 로컬 축(오브젝트 기준)**을 따라 회전합니다.
- 월드 축 기준으로 회전하려면 행렬을 사용해야 합니다.
- 예: obj.matrix_world = Matrix.Rotation(angle, 4, 'Z') @ obj.matrix_world.
예제 코드 모음 - 로컬 Z축에 15도 더하기 (안전한 방법)
import bpy, math
obj = bpy.data.objects.get("Cube_2_2")
if obj:
obj.rotation_mode = 'XYZ'
obj.rotation_euler[2] += math.radians(15) - 월드 Z축 기준 회전 (오브젝트 위치도 함께 회전)
import bpy, math
from mathutils import Matrix
obj = bpy.data.objects.get("Cube_2_2")
if obj:
angle = math.radians(15)
rot_mat = Matrix.Rotation(angle, 4, 'Z')
obj.matrix_world = rot_mat @ obj.matrix_world - Quaternion 모드로 안전하게 회전 적용 (gimbal lock 회피 목적)
import bpy, math
from mathutils import Quaternion
obj = bpy.data.objects.get("Cube_2_2")
if obj:
q = Quaternion((0, 0, 1), math.radians(15)) # Z축 회전 쿼터니언
obj.rotation_mode = 'QUATERNION'
obj.rotation_quaternion = q @ obj.rotation_quaternion - 주의사항, 팁
- 단위: Blender의 rotation_euler는 라디안을 사용합니다. math.radians()로 변환하세요.
- 회전 순서(오더): 'XYZ' 같은 순서에 따라 최종 방향이 달라질 수 있고, 특정 순서에서는 gimbal lock이 발생할 수 있습니다. 필요하면 쿼터니언을 사용하세요.
- 연산자 의존성: bpy.ops.transform.rotate 같은 연산자는 뷰/모드와 활성 오브젝트 상태에 의존하므로, 스크립트에서는 rotation_euler나 행렬/쿼터니언을 직접 조작하는 편이 더 예측 가능합니다.
"""
6. Files
7. Ref.
Happy Programming!
^.^;
'Graphics > 3D Graphics' 카테고리의 다른 글
| Blender 3D 입문 - 면의 분할 001 (0) | 2025.12.21 |
|---|---|
| Blender 3D Intro. Part - I (0) | 2025.11.12 |
| TrueSpace v7.6.1 and Blender 3D v4.4.3 (Freeware) (0) | 2025.05.20 |