Эти нормали треугольников - не то же самое, что вершинные нормали: те определены как среднее всех нормалей граней, использующих вершину, так что мы должны вычислить самостоятельно эти нормали треугольников. Это можно сделать посредством вычисления векторного произведения рёберных векторов, то есть, векторов, определенных двумя вершинами в конце каждого ребра. В показанных у нас примерах есть левый треугольник, его нормаль формируется взятием векторного произведения рёберных векторов 1→0 и 1→ 2, и треугольник справа, для него вычисляем векторное произведение рёберных векторов 2→1 и 2→3.
Не имеет значения, просматриваем мы наши рёбра по часовой стрелке или против часовой стрелки, но мы должны быть осторожными, чтобы последовательно упорядочивать рёбра при расчете векторных произведений, поскольку знак может поменяться. Как только у нас будут наши нормали треугольников, мы можем проверить, указывают ли они в одном и том же направлении, удостоверившись, что все компоненты (х, у, и z) одного вектора масштабированы одинаково по сравнению с соответствующими компонентами второго вектора. Тем не менее, чтобы дать нам отчасти большую гибкость, мы хотели бы вычислять угол между нормалями треугольников и выбирать грань, только если этот угол превышает некоторый минимум. Нам не нужно самим разрабатывать такую функцию, поскольку модуль
Возможно построить четыре различных треугольника в четырёхугольнике, но не нужно сравнивать их все - нормалей любых двух треугольников будет достаточно, поскольку перемещение одной вершины в четырёхугольнике изменит нормали трёх из четырех возможных треугольников.
Вооружившись всей этой информацией, набросаем схему для нашего инструмента, она будет выглядеть так:
1. Показать всплывающий диалог для ввода минимального угла.
2. Проверить, что активный объект - это меш, и он в режиме
редактирования.
3. Включить режим выбора граней
4. Для всех граней проверить, является ли она четырёхугольником, и если так:
• Вычислить нормаль треугольника, определенного вершинами 0, 1, и 2
• Вычислить нормаль треугольника, определенного вершинами 1, 2, и 3
• Вычислить угол между нормалями
• Если угол > минимального угла, выбрать грань Это транслируется в следующий код для фактического обнаружения и выбора (полный скрипт предоставлен как
warpselect.py):
def warpselect(me,maxangle=5.0):
for face in me.faces:
if len(face.verts) == 4:
n1 = (face.verts[0].co - \
face.verts[1].co ).cross(
face.verts[2].co - face.verts[1].co )
n2 = ( face.verts[1].co - \
face.verts[2].co ).cross(
face.verts[3].co - face.verts[2].co )
a = AngleBetweenVecs(n1,n2)
if a > maxangle :
face.sel = 1
Как Вы можете видеть, наша схема почти взаимно-однозначно соответствует коду. Заметьте, что
selectmode = Blender.Mesh.Mode()
Blender.Mesh.Mode(selectmode |
Blender.Mesh.SelectModes.FACE)
Чтобы проиллюстрировать малоизвестный факт о том, что режимы выбора не являются взаимоисключающими, мы установили режим
Выбор слишком острых граней
Существует много инструментов для выбора граней, с которыми в некоторых случаях громоздко работать. Блендер имеет встроенные инструменты, чтобы выбирать грани, которые имеют слишком маленькую площадь или которые имеют слишком короткий периметр. Тем не менее, этого недостаточно для выбора граней с рёбрами, которые формируют углы острее, чем некоторый предел. В некоторых задачах моделирования было бы очень удобно иметь возможность выбирать такие грани, так как они обычно трудны для манипуляций и могут вызывать безобразные артефакты при применении модификатора subsurface или при деформации меша.