Было бы скучно если бы в blender не было модуля mathutils (http://www.blender.org/documentation/blender_python_api_2_62_release/mathutils.html)
Этот модуль предоставляет доступ к таким классам как Color, Euler, Matrix, Quaternion, Vectors.
Если нам нужно сделать модификацию меша, то модуль mathutils предоставит широкий набор возможностей.
Итак то что касается векторов:
Создать вектор можно задав три координаты (x,y,z)
import bpy
import mathutils
a = mathutils.Vector((0.0, 1.0, 2.0))
b = mathutils.Vector((1.0, 4.0, 1.0))
print("Вектор а",a)
print("Вектор в",b)
Вектор а <Vector (0.0000, 1.0000, 2.0000)>
Вектор в <Vector (1.0000, 4.0000, 1.0000)>
Если нужно сделать нормализацию вектора:
b.normalize()
print("Нормализованный вектор",b)
print("Длина вектора",b.length)
Нормализованный вектор <Vector (0.2357, 0.9428, 0.2357)>
Длина вектора 1.0000000707805132
Теперь о вкусностях!
операции над векторами :
c=a+b
print("a+b",c)
c=a-b
print("a-b",c)
c=a*b
print("a*b",c)
c=a*3.7
print("a*3.7",c)
a+b <Vector (0.2357, 1.9428, 2.2357)>
a-b <Vector (-0.2357, 0.0572, 1.7643)>
a*b 1.4142136573791504
a*3.7 <Vector (0.0000, 3.7000, 7.4000)>
Угол между двумя векторами:
u=a.angle(b)
print("Угол между двумя векторами",u)
Угол между двумя векторами 0.8860771059989929
Векторное произведение (cross product) и скалярное произведение (dot product):
c=a.cross(b)
print("Векторное произведение",c)
c=a.dot(b)
print("скалярное произведение",c)
Векторное произведение <Vector (-1.6499, 0.4714, -0.2357)>
скалярное произведение 1.4142136573791504
Интерполяция между двумя векторами, где f - фактор интерполяции от 0 до 1
for i in range(11):
f=i/10
c=a.lerp(b,f)
print(f,c)
0.0 <Vector (0.0000, 1.0000, 2.0000)>
0.1 <Vector (0.0236, 0.9943, 1.8236)>
0.2 <Vector (0.0471, 0.9886, 1.6471)>
0.3 <Vector (0.0707, 0.9828, 1.4707)>
0.4 <Vector (0.0943, 0.9771, 1.2943)>
0.5 <Vector (0.1179, 0.9714, 1.1179)>
0.6 <Vector (0.1414, 0.9657, 0.9414)>
0.7 <Vector (0.1650, 0.9600, 0.7650)>
0.8 <Vector (0.1886, 0.9542, 0.5886)>
0.9 <Vector (0.2121, 0.9485, 0.4121)>
1.0 <Vector (0.2357, 0.9428, 0.2357)>
Негатив, проекция вектора a на вектор b, отражение вектора:
c=a
c.negate()
print("негатив",c)
c=a.project(b)
print("проекция",c)
c=a.reflect(b)
print("отражение",c)
негатив <Vector (-0.0000, -1.0000, -2.0000)>
проекция <Vector (-0.3333, -1.3333, -0.3333)>
отражение <Vector (0.6667, 1.6667, -1.3333)>
поворот вектора:
c=a.rotate(Euler or Quaternion or Matrix) для поворота нужно указать один из компонентов
модуль mathutils.geometry
Площадь треугольника
area_tri(v1, v2, v3)
Расстояние от точки до плоскости
distance_point_to_plane(pt, plane_co, plane_no)
Пересечение двух линий
intersect_line_line(v1, v2, v3, v4)
Пересечение лини и плоскости
intersect_line_plane(line_a, line_b, plane_co, plane_no, no_flip=False)
Пересечение линии сферы
intersect_line_sphere(line_a, line_b, sphere_co, sphere_radius, clip=True)
Пересечение двух планов
intersect_plane_plane(plane_a_co, plane_a_no, plane_b_co, plane_b_no)
Очень нужная вещь - тесселяция полигона
tesselate_polygon(veclist_list)
... при подготовке модели к печати мне нужно было провести несколько тестов меша на наличие пересечений файсов ...
... видимо отсутствие меха в рендере cycles настолько печалит, что входе этих экспериментов как-то само собой получил такое направление ...
... суть проста - для каждого фейса найти нормаль и откинуть от него пирамидку ...
... то есть если файс задан векторами p0, p1, p2 , тогда вектор нормали к поверхности фейса будет n = normal(p0,p1,p2), а вектор вершины пирамидки pn = pc + n, где собственно pc - это вектор центра фейса равный (p0+p1+p2)/3 ...
... коэффициент nkf определяет высоту пирамидки, мну взял 0.3 ...
... для каждого фейса это делает вот такая процедура:
def test(qverts,qedges,qfaces,nv,edges,nodes):
nkf = 0.3
p0 = nodes[nv[0]].co
p1 = nodes[nv[1]].co
p2 = nodes[nv[2]].co
pc = (p0 + p1 + p2) / 3
pn = pc + mathutils.geometry.normal(p0,p1,p2) * nkf
last=len(qverts)
qverts.extend([pn,p0,p1,p2])
qfaces.extend([[last,last+1,last+2],[last,last+2,last+3],[last,last+3,last+1]])
... на рисунке 1 представлена Сюзанна, а на рисунках 2,3,4 она же с различными параметрами модификатора сглаживания, который определяет количество разбиений и следовательно количество фейсов и в итоге количество пирамидок ...
1
(http://content.foto.mail.ru/mail/unixinfo/_myphoto/s-285.png)
2 k = 1
(http://content.foto.mail.ru/mail/unixinfo/_myphoto/s-286.png)
3 k = 2
(http://content.foto.mail.ru/mail/unixinfo/_myphoto/s-287.png)
4 k = 3
(http://content.foto.mail.ru/mail/unixinfo/_myphoto/s-288.png)
... вот полный текст кода, а во вложении сам файл с моделью ...
import bpy
import mathutils, math, struct
def make_mesh(name):
me = bpy.data.meshes.new(name)
ob = bpy.data.objects.new(name, me)
bpy.context.scene.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 test(qverts,qedges,qfaces,nv,edges,nodes):
nkf = 0.3
p0 = nodes[nv[0]].co
p1 = nodes[nv[1]].co
p2 = nodes[nv[2]].co
pc = (p0 + p1 + p2) / 3
pn = pc + mathutils.geometry.normal(p0,p1,p2) * nkf
last=len(qverts)
qverts.extend([pn,p0,p1,p2])
qfaces.extend([[last,last+1,last+2],[last,last+2,last+3],[last,last+3,last+1]])
def main():
obj = bpy.data.objects["Cube"]
mesh = obj.to_mesh(bpy.context.scene, True, 'PREVIEW')
faces = mesh.tessfaces
edges = mesh.edges
nodes = mesh.vertices
print('%d' % len(edges))
print(' %d\n' % len(faces))
qverts=[]
qedges=[]
qfaces=[]
for face in faces:
vertices = face.vertices[:]
if len(vertices) == 4:
test(qverts,qedges,qfaces,(vertices[0], vertices[1], vertices[2]),edges,nodes)
test(qverts,qedges,qfaces,(vertices[2], vertices[3], vertices[0]),edges,nodes)
else:
test(qverts,qedges,qfaces,vertices,edges,nodes)
ob=make_mesh("Test")
add_data(ob,qverts,qedges,qfaces)
main()
[вложение удалено Администратором]