파이선 스크립트 방카 블렌더로 만들기 blender
2026.01.17 03:45
import bpy
import bmesh
import math
class BangkaArchitect:
def __init__(self, length=8.0, beam=1.0, height=0.75): # 폭을 약간 넓혀 안정감 추가
self.L = length # 선체 길이
self.W = beam # 선체 최대 폭
self.H = height # 선체 높이
self.materials = {}
self.setup_materials()
def setup_materials(self):
"""재료별 쉐이더 설정"""
mats = {
"FRP_Hull": (0.7, 0.7, 0.7, 0.9), # FRP 외판 (반투명도 약간 줄임)
"FRP_Bottom": (0.2, 0.4, 0.8, 1.0), # 선체 하단색 (깊은 바다색)
"Bamboo_Core": (0.8, 0.7, 0.4, 1.0), # 대나무 합판
"Hardwood": (0.4, 0.2, 0.1, 1.0), # 강화 목재 (상단 트림, 엔진박스)
"Bamboo_Outrigger": (0.7, 0.6, 0.4, 1.0), # 아웃리거 대나무
"Metal_Fasteners": (0.6, 0.6, 0.6, 1.0) # 금속 부품 (연결대 등)
}
for name, color in mats.items():
mat = bpy.data.materials.new(name=name)
mat.use_nodes = True
nodes = mat.node_tree.nodes
bsdf = nodes.get("Principled BSDF")
if bsdf:
bsdf.inputs[0].default_value = color
if color[3] < 1.0: # 투명도 설정
mat.blend_method = 'BLEND'
bsdf.inputs['Alpha'].default_value = color[3]
self.materials[name] = mat
def create_v_hull(self):
"""선체 외판 생성 (V-Hull) - 상단 곡률과 하단 색상 분할"""
mesh = bpy.data.meshes.new("HullMesh")
obj = bpy.data.objects.new("Main_Hull_FRP", mesh)
bpy.context.collection.objects.link(obj)
bm = bmesh.new()
seg_y = 80 # 정밀도 더 향상
# 선체 상단과 하단이 분리되도록 정점 생성
verts = []
for i in range(seg_y + 1):
y = -self.L/2 + (self.L * i / seg_y)
t = i / seg_y
# 유선형 폭/높이 계산
curve_factor = math.sin(math.pi * t)
w = self.W * curve_factor * 0.9
h = self.H * (0.2 + 0.8 * curve_factor)
# 상단부 정점 (곡선)
verts.append(bm.verts.new((w/2, y, h*1.05)))
verts.append(bm.verts.new((-w/2, y, h*1.05)))
# 바닥부 정점 (V-hull)
verts.append(bm.verts.new((0, y, -0.05))) # 바닥 중앙선 (물에 잠기는 부분)
verts.append(bm.verts.new((w/2 * 0.8, y, h*0.3))) # 중간지점
verts.append(bm.verts.new((-w/2 * 0.8, y, h*0.3)))
bm.verts.ensure_lookup_table()
faces_top = []
faces_bottom = []
for i in range(seg_y):
# 상단 곡면 (FRP_Hull 색상)
idx_top_start = i * 5
idx_top_next = (i + 1) * 5
faces_top.append(bm.faces.new((verts[idx_top_start], verts[idx_top_next], verts[idx_top_next+1], verts[idx_top_start+1]))) # 우현 상단
faces_top.append(bm.faces.new((verts[idx_top_start], verts[idx_top_start+2], verts[idx_top_next+2], verts[idx_top_next]))) # 좌현 상단
# 하단 곡면 (FRP_Bottom 색상)
faces_bottom.append(bm.faces.new((verts[idx_top_start+2], verts[idx_top_next+2], verts[idx_top_next+3], verts[idx_top_start+3]))) # 바닥 우측
faces_bottom.append(bm.faces.new((verts[idx_top_start+2], verts[idx_top_start+4], verts[idx_top_next+4], verts[idx_top_next+2]))) # 바닥 좌측
bm.to_mesh(mesh)
# 재료 슬롯 할당
obj.data.materials.append(self.materials["FRP_Hull"])
obj.data.materials.append(self.materials["FRP_Bottom"])
# 면에 재료 할당
for face in faces_top:
face.material_index = 0
for face in faces_bottom:
face.material_index = 1
bm.free()
def create_bamboo_grid_system(self):
"""내부 대나무 격자 보강재 (가로 늑골 및 세로 스트링거)"""
grid_spacing = 0.35
num_ribs = int(self.L / grid_spacing)
for i in range(num_ribs):
y_pos = -self.L/2.1 + (i * grid_spacing)
t = (y_pos + self.L/2) / self.L
curve = math.sin(math.pi * t)
if curve < 0.1: continue
w_at_pos = self.W * curve * 0.8 # 선체 폭에 맞춰 조정
bpy.ops.mesh.primitive_cube_add(size=1, location=(0, y_pos, 0.15))
rib = bpy.context.active_object
rib.scale = (w_at_pos, 0.03, 0.08)
rib.data.materials.append(self.materials["Bamboo_Core"])
# 세로 스트링거 (3개)
for side_offset in [-0.2, 0, 0.2]:
bpy.ops.mesh.primitive_cylinder_add(radius=0.025, depth=self.L*0.95, location=(side_offset, 0, 0.05))
st = bpy.context.active_object
st.rotation_euler[0] = math.pi/2 # 90도 회전
st.data.materials.append(self.materials["Bamboo_Core"])
def create_deck_and_gunwale(self):
"""갑판 및 상단 트림 (강화 목재)"""
# 상단 트림 (Gunwale) - 배의 끝선 강화
for side in [-1, 1]:
bpy.ops.mesh.primitive_cube_add(size=1, location=(self.W*0.48*side, 0, self.H*0.95))
gunwale = bpy.context.active_object
gunwale.scale = (0.05, self.L*0.98, 0.1)
gunwale.data.materials.append(self.materials["Hardwood"])
# 갑판 (단순화를 위해 중앙에 판 형태로)
bpy.ops.mesh.primitive_cube_add(size=1, location=(0, self.L*0.1, self.H*0.85))
deck = bpy.context.active_object
deck.scale = (self.W*0.7, self.L*0.6, 0.03) # 배 길이의 60% 정도만 갑판으로
deck.data.materials.append(self.materials["Hardwood"])
def create_engine_and_seating(self):
"""엔진 마운트 및 좌석"""
# 엔진 박스 (후미)
bpy.ops.mesh.primitive_cube_add(size=1, location=(0, -self.L*0.4, 0.3))
eng_box = bpy.context.active_object
eng_box.scale = (self.W*0.4, 0.8, 0.4)
eng_box.data.materials.append(self.materials["Hardwood"])
# 좌석 (중앙 2개)
for y_pos_offset in [0.1, 0.3]:
bpy.ops.mesh.primitive_cube_add(size=1, location=(0, self.L * y_pos_offset, self.H*0.7))
seat = bpy.context.active_object
seat.scale = (self.W*0.6, 0.5, 0.05)
seat.data.materials.append(self.materials["Hardwood"])
def create_katig_system(self):
"""아웃리거 (카티그) 시스템"""
aka_y_positions = [-1.5, 0, 1.5] # 3개의 연결대
aka_width = 5.8 # 연결대 길이
for y in aka_y_positions:
# 아웃리거 연결대 (Akas)
bpy.ops.mesh.primitive_cylinder_add(radius=0.04, depth=aka_width, location=(0, y, self.H*0.8))
aka = bpy.context.active_object
aka.rotation_euler[1] = math.pi/2 # 90도 회전
aka.data.materials.append(self.materials["Bamboo_Outrigger"])
# 연결대와 선체 사이 지지대 (선체에 붙는 부분)
for side in [-1, 1]:
bpy.ops.mesh.primitive_cube_add(size=1, location=(self.W*0.45*side, y, self.H*0.75))
brace = bpy.context.active_object
brace.scale = (0.05, 0.15, 0.1)
brace.rotation_euler[2] = math.pi/4 if side == 1 else -math.pi/4 # 사선으로 연결
brace.data.materials.append(self.materials["Hardwood"])
# 대나무 부표 (Floaters)
for x in [-aka_width/2, aka_width/2]:
bpy.ops.mesh.primitive_cylinder_add(radius=0.12, depth=self.L*0.9, location=(x, 0, 0.1))
floater = bpy.context.active_object
floater.rotation_euler[0] = math.pi/2 # 90도 회전
floater.data.materials.append(self.materials["Bamboo_Outrigger"])
# 부표와 연결대 연결하는 끈 (단순화된 실린더)
for y_con in [-self.L/3, self.L/3]:
bpy.ops.mesh.primitive_cylinder_add(radius=0.01, depth=aka_width-self.W*1.5, location=(0, y_con, 0.5))
rope = bpy.context.active_object
rope.rotation_euler[1] = math.pi/2
rope.data.materials.append(self.materials["Metal_Fasteners"]) # 끈은 금속 느낌으로
def add_annotations(self):
"""화면에 설계 정보 텍스트 추가"""
info = [
("PROJECT: Jaksim Hybrid 8M", (4, 0, 2.5)),
("TYPE: Bamboo Sandwich (One-off)", (4, 0, 2.1)),
("SPEC: No External Keel / V-Hull", (4, 0, 1.7)),
("DATA: PHP 80,000 Material Estimate", (4, 0, 1.3))
]
for text, loc in info:
bpy.ops.object.text_add(location=loc)
t_obj = bpy.context.active_object
t_obj.data.body = content
t_obj.scale = (0.35, 0.35, 0.35)
t_obj.rotation_euler[0], t_obj.rotation_euler[2] = math.pi/2, math.pi/2
def main():
# 장면 초기화
bpy.ops.object.select_all(action='SELECT')
bpy.ops.object.delete()
# 아키텍처 인스턴스 생성 및 실행
builder = BangkaArchitect()
builder.create_v_hull()
builder.create_bamboo_grid_system()
builder.create_deck_and_gunwale()
builder.create_engine_and_seating()
builder.create_katig_system()
builder.add_annotations()
if __name__ == "__main__":
main()
Comment 5
-
마이닉
2026.01.17 03:46

-
마이닉
2026.01.17 03:46

-
마이닉
2026.01.17 03:47

-
마이닉
2026.01.17 03:48

-
마이닉
2026.01.17 23:04

import bpy
import bmesh
import mathdef create_jaksim_professional_hull():
# 1. 초기화 (기존 객체 삭제)
bpy.ops.object.select_all(action='SELECT')
bpy.ops.object.delete()# --- 설계 파라미터 (8미터급) ---
L = 8.0 # 전체 길이
W = 0.8 # 선체 폭
H = 0.7 # 선체 높이
KEEL_RADIUS = 0.15 # 하단 통나무 용골 두께
RIB_COUNT = 18 # 늑골 개수 (영상처럼 촘촘하게)# 2. 하단 통나무 용골 (The Dugout Base - 영상 [00:02:27] 부분 재현)
# 영상에서 보는 가장 기초가 되는 깎아 만든 통나무 베이스입니다.
bpy.ops.mesh.primitive_cylinder_add(radius=KEEL_RADIUS, depth=L*0.9, location=(0, 0, 0))
keel = bpy.context.active_object
keel.name = "Traditional_Log_Keel"
keel.rotation_euler[0] = 1.5708 # 90도 회전
keel.scale = (1.0, 1.0, 0.4) # 약간 납작한 통나무 형태
# 3. 선체 외판 (The Hull Shell - 영상 속 뾰족한 주둥이 라인)
# 영상의 배처럼 앞뒤가 날렵하게 솟아오른 형태를 수식으로 생성합니다.
mesh = bpy.data.meshes.new("BangkaHull")
hull_obj = bpy.data.objects.new("Main_Hull", mesh)
bpy.context.collection.objects.link(hull_obj)
bm = bmesh.new()
segments = 60
for i in range(segments + 1):
t = i / segments
y = -L/2 + (L * t)
# 필리핀 방카 특유의 앞뒤가 솟은 곡률 계산
lift = (math.pow((t - 0.5) * 2, 2)) * 0.4
# 폭 계산 (중앙은 넓고 양끝은 뾰족하게)
width_factor = math.sin(math.pi * t)
curr_w = W * width_factor
curr_h = H * (0.5 + 0.5 * width_factor) + lift
# 정점 생성 (V자 단면)
bm.verts.new((0, y, lift)) # 바닥 라인
bm.verts.new((curr_w/2, y, curr_h)) # 우측 상단
bm.verts.new((-curr_w/2, y, curr_h)) # 좌측 상단bm.verts.ensure_lookup_table()
for i in range(segments):
idx = i * 3
# 면 생성 (바닥에서 벽면으로 이어지는 구조)
bm.faces.new((bm.verts[idx], bm.verts[idx+3], bm.verts[idx+4], bm.verts[idx+1]))
bm.faces.new((bm.verts[idx], bm.verts[idx+2], bm.verts[idx+5], bm.verts[idx+3]))
bm.to_mesh(mesh)
bm.free()# 두께와 부드러운 곡면 적용 (작업자에게 보여줄 완성도)
bpy.context.view_layer.objects.active = hull_obj
bpy.ops.object.modifier_add(type='SOLIDIFY')
hull_obj.modifiers["Solidify"].thickness = 0.02
bpy.ops.object.shade_smooth()# 4. 내부 늑골 시스템 (Internal Ribs - 영상 속 뼈대 작업 상태)
# 영상에서 목수들이 하나하나 박고 있는 갈비뼈 뼈대입니다.
for i in range(RIB_COUNT):
y_pos = -L/2.2 + (i * (L*0.9 / (RIB_COUNT-1)))
t_pos = (y_pos + L/2) / L
w_rib = W * math.sin(math.pi * t_pos) * 0.85
h_lift = (math.pow((t_pos - 0.5) * 2, 2)) * 0.4
if w_rib > 0.05:
# 늑골 (Rib) 생성
bpy.ops.mesh.primitive_cube_add(size=1, location=(0, y_pos, h_lift + 0.1))
rib = bpy.context.active_object
rib.scale = (w_rib, 0.04, 0.08)
rib.name = f"Rib_{i}"# 5. 재질 설정 (나무 느낌)
def add_wood_mat(obj, color):
mat = bpy.data.materials.new(name="WoodMat")
mat.use_nodes = True
mat.node_tree.nodes["Principled BSDF"].inputs[0].default_value = color
mat.diffuse_color = color # 뷰포트 색상
obj.data.materials.append(mat)add_wood_mat(keel, (0.2, 0.1, 0.05, 1)) # 어두운 통나무
add_wood_mat(hull_obj, (0.6, 0.5, 0.3, 1)) # 합판 색상create_jaksim_professional_hull()
| No. | Subject | Author | Date | Views |
|---|---|---|---|---|
| 12 |
진흙 뒤집어쓰고 거리 나온 필리핀 청년들···‘Z세대 아시아의 봄’ 합류
| 마이닉 | 2025.09.21 | 0 |
| 11 | 50+ 오리알의 필리핀 정착기, 그 진실을 파헤치는 섹식주 | 마이닉 | 2025.09.25 | 0 |
| 10 |
방카
[35] | 마이닉 | 2025.12.25 | 0 |
| 9 |
ebike shop shopee
| 마이닉 | 2025.12.28 | 0 |
| 8 | 바랑가이 반티게(Barangay Bantigue)**에 있는 'Multi-Species Marine Hatchery' 근처를 가보시면 FRP 보트들이 보일 겁니다. | 마이닉 | 2025.12.31 | 0 |
| 7 | 반타얀섬(Bantayan Island)은 필리핀 내에서도 해산물과 가공되지 않은 신선한 식재료가 풍부하기로 유명한 곳 | 마이닉 | 2026.01.11 | 0 |
| 6 |
Ebike Electric motorcycle Electric bikes
[2] | 마이닉 | 2026.01.11 | 0 |
| 5 | 현지 여성들에게 보낼 메시지 [2] | 마이닉 | 2026.01.16 | 0 |
| » | 파이선 스크립트 방카 블렌더로 만들기 blender [5] | 마이닉 | 2026.01.17 | 0 |
| 3 | 외국인을 위한 필리핀 뉴스채널 | 마이닉 | 2026.01.17 | 0 |
| 2 |
ebike 이바이크
[1] | 마이닉 | 2026.01.18 | 0 |
| 1 |
bbq 바베큐그릴
[1] | 마이닉 | 2026.01.20 | 0 |