Blender > BLENDERMETRY (Блендерметрия)
Blender и Matt Shlian
(1/1)
Николай Николаев:
В продолжении темы 3D панель пирамиды волной, в которой упоминалось творческое бумажное моделирование Matt Shlian, добавлю несколько строк о пользе математики и кодерства, опять же с использованием Blender API.
Что требовалось:
Что получилось (viewport):
https://yadi.sk/i/JwiY_kUpfzkv-A
Как делалось:
Во-первых, сейчас не требуется визуализация картинки, поскольку в дальнейшем требуется изготовить бумажную модель (панель). То есть по факту будет множество выкроек для изготовления элементов и сборка из этих элементов панели.
По сути требуется только геометрия.
Этап 1 — построить соты. Строим двумя циклами как обычно по горизонтали и вертикали, но нечетные вертикальные ряды делаем со смещением и на один элемент больше.
--- Код: (python) ---# generate piramids
ry = radius*2*math.cos(math.radians(30))
rx = radius*3*math.sin(math.radians(30))
for x in range(cols):
dy = 1 if (x % 2) else 0
for y in range(rows+dy):
--- Конец кода ---
В теле цикла формируем два вектора:
вектор позиции пирамиды:
--- Код: (python) ---v0=mathutils.Vector((x*rx,(-y+dy/2)*ry,0.0))
--- Конец кода ---
и вектор смещения вершины пирамиды относительно основания:
--- Код: (python) ---vd = cfunc(x/(cols-1),y/(rows-1),scale)
--- Конец кода ---
Важно, что этот вектор на самом деле определяется пользовательской функций cfunc, ссылка на которую передается в рутину. Пользовательская функция принимает всего три параметра — относительные координаты основания пирамиды, где X и Y могут принимать значение от 0 до 1 и некоторый масштабный коэффициент, который определяет силу воздействия смещения на вершину пирамиды.
Этап 2 — определение пользовательской функции.
Как уже было выше сказано, пользовательская функция должна определять смещение вершины пирамиды относительно основания и принимает всего три параметра x,y,s и возвращает вектор смещения умноженный на силу влияния (s).
Для примера будем использовать такую функцию, которая приближенно дает похожую геометрию как на исходном изображении.
--- Код: (python) ---def sin_cos(x,y,s):
# user define function
# return offset vector*scale
A = 3.8
B = 1.8
C = 4.2
D = 1.8
return mathutils.Vector((math.cos(A*(B*x+y)),math.sin(C*(D*x+y)),0.0))*s
--- Конец кода ---
Этап 3 — запускаем рутину.
Делаем автосохранение! Необязательно, но мне помогло.
--- Код: (python) ---#autosave
bpy.ops.wm.save_as_mainfile(filepath=bpy.data.filepath)
--- Конец кода ---
Строим 26 рядов по 33 пирамиды в ряду с радиус основания 1 и высотой 3, силой влияния смещения 2 и пользовательской функцией sin_cos
--- Код: (python) ---#routine(rows,cols,radius,height,function)
routine(26,33,1.0,3.0,2,sin_cos)
--- Конец кода ---
Естественно, все параметры можно менять, а самое важно можно и нужно переписать пользовательскую функцию под требуемые задачи.
Весь код:
--- Код: (python) ---import bpy
import mathutils
import math
def make_mesh(name):
me = bpy.data.meshes.new(name)
ob = bpy.data.objects.new(name, me)
bpy.data.collections[0].objects.link(ob)
return ob
def add_data(ob,verts,edges,faces):
me = ob.data
me.name = ob.name +' mesh'
me.from_pydata(verts,edges,faces)
me.update()
def emm(v0,vd,r,h):
verts = []
edges = []
faces = []
da = 30
for i in range(6):
a = 60*i
a1 = math.radians(a-da)
a2 = math.radians(a+da)
v1 = v0 + mathutils.Vector((r*math.sin(a1), r*math.cos(a1),0.0))
v2 = v0 + mathutils.Vector((r*math.sin(a2), r*math.cos(a2),0.0))
last=len(verts)
vp = v0+vd+mathutils.Vector((0,0,h))
verts.extend([vp,v1,v2])
faces.append([last,last+1,last+2])
return verts,edges,faces
def routine(rows,cols,radius,height,scale,cfunc):
# remove all objects
for ob in bpy.data.objects:
ob.parent = None
bpy.data.objects.remove(ob, do_unlink=True,do_ui_user=True)
# init material
mat = bpy.data.materials.get("Material")
if mat is None:
mat = bpy.data.materials.new(name="Material")
# generate piramids
ry = radius*2*math.cos(math.radians(30))
rx = radius*3*math.sin(math.radians(30))
for x in range(cols):
dy = 1 if (x % 2) else 0
for y in range(rows+dy):
v0=mathutils.Vector((x*rx,(-y+dy/2)*ry,0.0))
vd = cfunc(x/(cols-1),y/(rows-1),scale)
verts, edges, faces = emm(v0,vd,radius,height)
ob=make_mesh('frag_'+str(x)+'_'+str(y))
add_data(ob,verts,edges,faces)
if ob.data.materials:
ob.data.materials[0] = mat
else:
ob.data.materials.append(mat)
def sin_cos(x,y,s):
# user define function
# return offset vector*scale
A = 3.8
B = 1.8
C = 4.2
D = 1.8
return mathutils.Vector((math.cos(A*(B*x+y)),math.sin(C*(D*x+y)),0.0))*s
#autosave
bpy.ops.wm.save_as_mainfile(filepath=bpy.data.filepath)
#bpy.ops.wm.open_mainfile(filepath=bpy.data.filepath)
#routine(rows,cols,radius,height,function)
routine(26,33,1.0,3.0,2,sin_cos)
--- Конец кода ---
.blend файл с примером:
https://yadi.sk/d/HH6IHMiPF5MEUw
Навигация
Перейти к полной версии