Загрузка данных
"""
Пластина-параллелограмм с надписью "REPUBLIC OF GAMERS" (без логотипа - место слева свободно).
Запуск: Blender -> Scripting -> Создать -> вставить код -> Текст -> Запустить скрипт.
Единицы: 1 единица Blender = 1 мм. Лицевая сторона смотрит в -Y (вид спереди: Numpad 1).
"""
import os
import bpy
import bmesh
from math import pi
# ---------- Настройки ----------
W = 60.0 # ширина пластины по горизонтали, мм
H = 10.5 # высота, мм
SLOPE = 0.85 # наклон боковых граней (смещение по X на 1 мм высоты)
T = 1.2 # толщина пластины, мм
INSET = 0.9 # отступ внутренней панели от края, мм
RAISE = 0.15 # на сколько внутренняя панель выступает вперёд, мм
TEXT_X = -0.08 # начало текста: доля ширины от центра (0 = центр, -0.5 = левый край)
TEXT_SIZE = 3.3 # размер шрифта, мм
LINE_GAP = 3.7 # расстояние между строками, мм
LETTER_SPACE = 1.15 # межбуквенный интервал
LINE1, LINE2 = "REPUBLIC OF", "GAMERS"
# Шрифт. Если у тебя есть файл шрифта ROG (или любой другой), впиши путь, например:
# FONT_PATH = r"C:\Users\Имя\Downloads\ROG_Fonts.ttf"
FONT_PATH = ""
TEXT_BOLD = 0.035 # утолщение букв, мм (0 = без утолщения; 0.05 = заметно жирнее)
TEXT_WIDTH = 1.0 # растяжение букв по ширине (1.0 = как есть, 1.2 = шире)
PREFIX = "ROGPlate_"
# Если FONT_PATH пуст, пробуем жирные широкие шрифты Windows по порядку
FONT_CANDIDATES = [
r"C:\Windows\Fonts\ariblk.ttf", # Arial Black
r"C:\Windows\Fonts\arialbd.ttf", # Arial Bold
r"C:\Windows\Fonts\segoeuib.ttf", # Segoe UI Bold
"/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf",
]
# ---------- Материалы ----------
def make_material(name, c0, c1, metallic, rough, noise_scale=6.0, stretch=(1, 1, 1), bump=0.1):
mat = bpy.data.materials.get(name) or bpy.data.materials.new(name)
try:
mat.use_nodes = True
except Exception:
pass
nt = mat.node_tree
nt.nodes.clear()
out = nt.nodes.new("ShaderNodeOutputMaterial")
bsdf = nt.nodes.new("ShaderNodeBsdfPrincipled")
nt.links.new(bsdf.outputs["BSDF"], out.inputs["Surface"])
bsdf.inputs["Base Color"].default_value = c1
bsdf.inputs["Metallic"].default_value = metallic
bsdf.inputs["Roughness"].default_value = rough
try:
tc = nt.nodes.new("ShaderNodeTexCoord")
mp = nt.nodes.new("ShaderNodeMapping")
nt.links.new(tc.outputs["Object"], mp.inputs["Vector"])
mp.inputs["Scale"].default_value = tuple(noise_scale * s for s in stretch)
nz = nt.nodes.new("ShaderNodeTexNoise")
nz.inputs["Scale"].default_value = 1.0
nz.inputs["Detail"].default_value = 5.0
nt.links.new(mp.outputs["Vector"], nz.inputs["Vector"])
ramp = nt.nodes.new("ShaderNodeValToRGB")
ramp.color_ramp.elements[0].color = c0
ramp.color_ramp.elements[1].color = c1
nt.links.new(nz.outputs["Fac"], ramp.inputs["Fac"])
nt.links.new(ramp.outputs["Color"], bsdf.inputs["Base Color"])
bp = nt.nodes.new("ShaderNodeBump")
bp.inputs["Strength"].default_value = bump
bp.inputs["Distance"].default_value = 0.05
nt.links.new(nz.outputs["Fac"], bp.inputs["Height"])
nt.links.new(bp.outputs["Normal"], bsdf.inputs["Normal"])
except Exception as ex:
print("Текстуры материала", name, "не применены:", ex)
return mat
# ---------- Геометрия ----------
def parallelogram(w, h, slope):
"""Параллелограмм (x, z) с центром в начале координат, нижняя сторона сдвинута вправо."""
k = slope * h / 2
return [(-w / 2 - k, h / 2), (w / 2 - k, h / 2), (w / 2 + k, -h / 2), (-w / 2 + k, -h / 2)]
def prism(name, pts, y0, y1, mat):
"""Призма вдоль оси Y по контуру pts в плоскости XZ."""
n = len(pts)
verts = [(x, y0, z) for x, z in pts] + [(x, y1, z) for x, z in pts]
faces = [tuple(reversed(range(n))), tuple(n + i for i in range(n))]
for i in range(n):
j = (i + 1) % n
faces.append((i, j, n + j, n + i))
mesh = bpy.data.meshes.new(name)
mesh.from_pydata(verts, [], faces)
mesh.update()
obj = bpy.data.objects.new(name, mesh)
bpy.context.collection.objects.link(obj)
bm = bmesh.new()
bm.from_mesh(mesh)
bmesh.ops.recalc_face_normals(bm, faces=bm.faces)
bm.to_mesh(mesh)
bm.free()
obj.data.materials.append(mat)
return obj
def load_font():
paths = [FONT_PATH] if FONT_PATH else FONT_CANDIDATES
for p in paths:
try:
if p and os.path.exists(p):
f = bpy.data.fonts.load(p)
print("Шрифт:", p)
return f
except Exception as ex:
print("Не удалось загрузить шрифт", p, ":", ex)
print("Подходящий шрифт не найден, используется стандартный Bfont")
return None
def add_text(body, x, y, z, mat, name, font=None):
cu = bpy.data.curves.new(PREFIX + name, "FONT")
cu.body = body
cu.size = TEXT_SIZE
cu.align_x = "LEFT"
cu.align_y = "CENTER"
cu.space_character = LETTER_SPACE
cu.extrude = 0.06
cu.offset = TEXT_BOLD # утолщает контур букв
if font is not None:
cu.font = font
ob = bpy.data.objects.new(PREFIX + name, cu)
bpy.context.collection.objects.link(ob)
ob.rotation_euler = (pi / 2, 0, 0) # лицом к -Y, строка вдоль +X
ob.scale = (TEXT_WIDTH, 1.0, 1.0)
ob.location = (x, y, z)
ob.data.materials.append(mat)
return ob
def main():
for ob in list(bpy.data.objects):
if ob.name.startswith(PREFIX):
bpy.data.objects.remove(ob, do_unlink=True)
m_plate = make_material(PREFIX + "Silver", (0.55, 0.57, 0.60, 1), (0.85, 0.86, 0.88, 1),
1.0, 0.35, noise_scale=7.0, stretch=(8.0, 0.3, 0.3), bump=0.2)
m_panel = make_material(PREFIX + "Satin", (0.70, 0.71, 0.73, 1), (0.92, 0.93, 0.94, 1),
1.0, 0.5, noise_scale=12.0, stretch=(6.0, 0.3, 0.3), bump=0.08)
m_text = make_material(PREFIX + "Black", (0.005, 0.005, 0.006, 1), (0.02, 0.02, 0.025, 1),
0.0, 0.25, noise_scale=40.0, bump=0.02)
# основание и внутренняя панель
plate = prism(PREFIX + "Plate", parallelogram(W, H, SLOPE), 0.0, T, m_plate)
bev = plate.modifiers.new("Bevel", "BEVEL")
bev.width = 0.25
bev.segments = 3
panel = prism(PREFIX + "Panel", parallelogram(W - 2 * INSET, H - 2 * INSET, SLOPE),
-RAISE, 0.05, m_panel)
bev2 = panel.modifiers.new("Bevel", "BEVEL")
bev2.width = 0.08
bev2.segments = 2
# две строки текста справа, слева место под логотип
x = TEXT_X * W
y = -RAISE - 0.03
font = load_font()
add_text(LINE1, x, y, +LINE_GAP / 2, m_text, "Line1", font)
add_text(LINE2, x, y, -LINE_GAP / 2, m_text, "Line2", font)
# свет
ld = bpy.data.lights.new(PREFIX + "Light", "AREA")
ld.energy = 3000
ld.size = 60
lo = bpy.data.objects.new(PREFIX + "Light", ld)
bpy.context.collection.objects.link(lo)
lo.location = (10, -60, 40)
lo.rotation_euler = (pi / 2.6, 0, 0)
try:
for area in bpy.context.screen.areas:
if area.type == "VIEW_3D":
area.spaces[0].shading.type = "MATERIAL"
except Exception as ex:
print("Не удалось переключить вид:", ex)
print("Готово: пластина REPUBLIC OF GAMERS")
main()