Blender для начинающих/Python практика
Содержание コンテンツ
Blender 2.77 - теория 이론
Blender 2.77 - практика 实践
Blender 2.49 - теория 이론
Старый Blender Содержит информацию о Blender 2.49. После прочтения данной части книги Вы сможете назвать основные плюсы и минусы Blender 2.49. Blender 2.77 & 3DsMax 이론
Blender & 3DsMax Сравнение Blender, 3DsMax, Sweet Home и Art Of Illusion. После прочтения этой главы Вы будете немного знать о различиях этих программ. Программирование 이론
Дополнительное 이론
Постобработка изображений
Музыкальное сопровождение
Одни из главных классов Python: bpy.ops | bpy.data | bpy.types.ID
|
Ссылки на материалы |
---|
|
Возможно, Вас заинтересует следующее: |
О Blender 2.76 | Скачать Blender 2.76 |
Алгебраические задачи
[править]Перестановка значений переменных
[править]def Swap(a, b):
a = a + b
b = a - b
a = a - b
Циклы
[править]Пусть, имеется переменная a, значение которой после цикла while надо узнать. Пусть, inc - число, на которое увеличивается a. B - переменная, задающая условие в цикле:
while a знак B:
a = a + inc
inc - независимая переменная. Значение a приближается к значению B.
- Если неравенство нестрогое, то после цикла a = a + inc*(abs(B - a) // inc + 1).
- Если неравенство строгое, то рассматриваются два случая:
- Если B % inc != 0, то a = a + inc*(abs(B - a) // inc + 1).
- Если B % inc == 0, то a = a + inc*(abs(B - a) // inc).
Таким образом, если неравенство нестрогое или неравенство строгое и остаток от деления B на inc не равен 0, то a = a + inc*(abs(B - a) // inc + 1), а во всех остальных случаях a = a + inc*(abs(B - a) // inc)
Если a = B и неравенство нестрогое, то переменная a = a + inc.
Геометрические задачи
[править]Расположение точки на диагонали
[править]Пусть, имеется точка A(x, y), то будет или нет она располагается на диагонали, можно будет узнать так:
if math.fabs(x) == math.fabs(y):
print("Точка на диагонали")
math.fabs(x) возвращает модуль числа x.
Точка находится под прямой
[править]Пусть, имеется точка A(x, y), где x, y - нецелые числа. Уравнение прямой y = kx + b. Функция, возвращающая y в зависимости от x:
def getY(x, k, b):
return k*x+b
Узнать ниже ли точка прямой или нет, можно, подставив ее x в уравнение прямой:
if y < getY(x, y, k):
print("Точка под прямой.")
Точка на прямой
[править]Пусть, имеется точка A(x, y), где x, y - нецелые числа. Узнать на прямой ли точка или нет, можно, подставив ее x в уравнение прямой:
if y == getY(x, y, k):
print("Точка на прямой.")
Точка над прямой
[править]Пусть, имеется точка A(x, y), где x, y - нецелые числа. Узнать выше прямой ли точка или нет, можно, подставив ее x в уравнение прямой:
if y > getY(x, y, k):
print("Точка над прямой.")
Вычисление k перпендикулярной прямой
[править]Пусть, имеется точки A(x, y) и A(x2, y2), задающие прямые, где x, y - нецелые числа. То зная k первой прямой вычислить k для второй можно следующим образом:
import math
k2 = math.tan(math.atan(k)+90)
Вычисление координат точки пересечения прямых
[править]Пусть, прямые задаются такими уравнениями:
- y1 = k1*x + b1
- y2 = k2*x + b2
Приравняв их, получим: k1*x + b1 = k2*x + b2.
- k1*x - k2*x = b2 - b1
- x(k1 - k2) = b2 - b1
Следовательно, x = (b2 - b1)/(k1 - k2). Таким образом, узнать координаты точки пересечения прямых можно так:
x = (b2 - b1)/(k1 - k2)
y = k1*x + b1 # Без разницы, в уравнение какой прямой подставлять.
Вычисление коэффициента наклона прямой
[править]Пусть, прямая проходит через две точки: A(x, y) и B(x1, y1). Причем, точка B лежит правее и выше точки A. Тогда вычисление коэффициента k для уравнения прямой будет выглядеть следующим образом:
k = (y1 - y)/(x1 - x)
Столкновения
[править]Окружность с окружностью
[править]Если расстояние между радиусами окружностей больше суммы их радиусов, то они не пересекаются:
import math
if (math.sqrt((circle1.x - circle2.x)**2 + (circle1.y - circle2.y)**2) >= circle1.r + circle2.r):
print("Окружности не пересекаются.")
Здесь circle1 и circle2 - окружности.
Пересечение отрезков
[править]
Схема определения пересечения отрезков выглядит так:
Если проекции отрезков на ось X пересекаются:
- Найти точку пересечения прямых, на которых лежат отрезки.
- Если координата точки пересечения принадлежит одновременно двум проекциям отрезков на ось X, то:
- Отрезки пересекаются.
- Иначе:
- Отрезки не пересекаются.
Пусть, есть две точки, составляющих первый отрезок: A(x, y) и B(x1, y1). Пусть, есть две точки, составляющие второй отрезок: C(x2, y2) и D(x3, y3). Пусть, точки расположены по оси +X в таком порядке: A, B, C, D.
if ((x1 >= x3) and (x1 <= x4)) or ((x >= x3) and (x <= x4)):
intersectX = (b2 - b1)/(k1 - k2)
if ((intersectX >= x) and (intersectX <= x1)) or ((intersectX >= x2) and (intersectX <= x3)):
print('Отрезки пересекаются.')
else:
print('Отрезки не пересекаются.')
else:
print('Отрезки не пересекаются.')
Данная схема будет корректно работать лишь в том случае, если ни один из отрезков не перпендикулярен оси X.
Принципы написания UI
[править]Аббревиатура «UI» расшифровывается на русский язык как «пользовательский интерфейс».
Кнопки
[править]
Границей любой кнопки обычно является прямоугольник, поэтому проверка на принадлежность точки A(x, y) этому прямоугольнику можно задать следующим условием:
if (A.x >= button.x) and (A.y >= button.y) and (A.x <= button.x + button.width) and (A.y <= button.y + button.heigth):
- A.x - X координата точки
- A.y - Y координата точки
- button.x - X координата левого верхнего угла прямоугольника
- button.y - Y координата левого верхнего угла прямоугольника
- button.width - ширина прямоугольника
- button.height - высота прямоугольника
Ползунки
[править]Любой ползунок представляет собой два прямоугольника. Первый - границы ползунка, второй - значение ползунка. Напишем функцию, которая определит лежит ли точка в границах первого прямоугольника «border»:
def intersect(A, border):
if (A.x >= border.x) and (A.y >= border.y) and (A.x <= border.x + border.width) and (A.y <= border.y + border.heigth):
return True
else:
return False
Пусть, Вы перемещайте ползунок, то код для обработки изменения значения ползунка будет следующий:
if cursor.x < border.x:
value.x = border.x
elif cursor.x > border.x + border.width:
value.x = border.x + border.width
else:
value.x = cursor.x
Архитектура игровых классов
[править]При написании проекта следует определить будет ли он 2D или 3D игрой. С учетом этого, следует строить архетиктуру классов проекта.
2D игры - пример архитектуры классов
[править]class Object
# свойства
x_position, y_position, width, height, fill_color, border_color, border_width, filled, bordered
class Lamp(Object)
# свойства
energy, distance
class Dynamic(Object)
# свойства
mass, radius
Здесь основные свойства объекта занесены в один класс «Object», так как их мало.
3D игры - пример архитектуры
[править]Так как 3D игры - игры с более навороченной графикой, то было бы предпочтительнее использовать такую систему классов:
class Material
# свойства
fill_color, border_color, border_width, filled, bordered
class Object
# свойства
x_position, y_position, width, height
# ссылка на объект:
material
class Lamp(Object)
# свойства
energy, distance
class Dynamic(Object)
# свойства
mass, radius
Калькулятор
[править]Пусть, наш калькулятор поддерживает выражения вида a±b, a/b и a*b. Пусть, a, b € [0; 9]. Код калькулятора будет следующий:
while True:
text = input()
if len(text) != 3:
print("Длина строки не равна 3.")
else:
a = int(text[0])
b = int(text[2])
if text[1] == "+":
print(a + b)
elif text[1] == "-":
print(a - b)
elif text[1] == "/":
print(a / b)
elif text[1] == "*":
print(a * b)
else:
print("Недопустимая операция.")
Сортировки
[править]Диски
[править]Пусть, имеем три палки «A», «B» и «C», причем изначально все диски лежат на «A». Следует отсортировать диски по возрастанию (от верхнего к нижниму), если мы можем видеть только верхние диски.
Пока на палке «A» находится не ноль дисков:
- Перекинуть верхний диск с «A» на «B».
- Повторить цикл такое количество раз, которое равно n (n - количество дисков на «A»):
- Если диск на «B» меньше, чем на «A», то скинуть диск с «A» на «B».
- Перекинуть диск с «B» на «C».
- Перекинуть такое количество дисков с «B» на «A», которое равно n - m (n - количество всех дисков на «B», а m - количество циклов, уменьшенное на единицу).
- Перекинуть диск с «C» на «B».
Сортировка при помощи функций списков
[править]Самый неудачный, но возможный вариант сортировки представлен ниже:
def SortList(a):
b = list()
for i in range(0, len(a)):
m = a.min(a)
b.append(m)
a.remove(m)
return b
Недостатки:
- Используется два списка.
- Слишком много используется встроенных функций.
- Медленная сортировка.
Использование встроенных в Python функций не гарантирует быструю скорость работы алгоритма.
Сортировка пузырьком
[править]- Проходим по списку несколько раз, чтобы правильно отсортировать все элементы в правильном порядке. Не всегда после n-ной итерации все элементы списка будут отсортированы.
- Сначала мы ищем минимальный элемент во всем списке, потом - в его оставшейся части.
def SortList(a):
for i in range(0, len(a)):
for j in range(len(a) - 1, i, -1):
if a[j] < a[j-1]:
a[j], a[j - 1] = a[j - 1], a[j]
return a
def SortList(a):
for i in range(len(a) - 1, -1):
for j in range(0, i):
if a[j] < a[j + 1]:
a[j], a[j + 1] = a[j + 1], a[j]
return a
Сортировка выбором
[править]def SortList(a):
for i in range(0, len(a)):
for j in range(i + 1, len(a)):
if a[i] > a[j]:
a[i], a[j] = a[j], a[i]
return a
- Переменные i и j изменяются в одном направлении - увеличиваются.
- Сравнивая с все элементы списка, стоящие после a[i], с a[i], мы находим минимум из множества значений (a[i], a[len(a)-1]]. При следующей итерации новый минимум будет искаться из оставшихся элементов, поэтому следующий минимум будет больше предыдущего минимума.
Сортировка вставками
[править]Отличается от сортировки пузырьком тем, что:
- Переменные i и j изменяются в разных направлениях.
- Осуществляем меньше итераций, чем в сортировке пузырьком, так как мы не проходим уже отсортированные пары элементов, поскольку отсортировали их на более ранних итерациях цикла for.
def SortList(a):
for i in range(1, len(a)):
j = i
while (j > 0) and (a[j] < a[j - 1]):
a[i], a[j] = a[j], a[i]
j -= 1
return a
- В «range(1, len(a))» первым элементом множества значений установил 1, чтобы не проверять лишний раз условие «while j > 0 and a[j] < a[j - 1]».
- Условие «j > 0» требуется для того, чтобы предотвратить выход j - 1 за границы списка.
Алгоритм создания множеств
[править]def NewSet(a):
for i in range(0, len(a)):
j = i + 1
while j < len(a):
if a[j] == a[i]:
a.remove(a[j])
else:
j += 1
return a
Пусть, мы должны сравнивать все элементы списка с a[j]. Из этого следует то, что не все элементы со значением a[j] были удалены. Но это противоречит тому, что написано в теле цикла:
while j < len(a):
if a[j] == a[i]:
a.remove(a[j])
else:
j += 1
Таким образом, мы должны сравнивать все элементы с a[i], стоящие после a[i].
Другие алгоритмы
[править]Разделение строки по символам
[править]sym = []
sym.append(' ')
sym.append(';')
words = []
wI = 0
s = input()
i = 0
while i < len(s):
while (i < len(s)) and (s[i] in sym):
i += 1
while (i < len(s)) and not (s[i] in sym):
sym[wI] = sym[wI] + s[i]
i += 1
wI += 1
Алгоритм нахождения НОК
[править]НОК - наибольший общий делитель чисел M и N.
- Выводим сумму, так не знаем в какой переменной именно хранится НОК. Значение одной из двух переменных после последней итерации будет равно 0.
def NOK(a, b): while a != 0 and b != 0: if a > b: a = a % b else: b = b % a return a + b
- Ниже используется правило «Если M>N, то НОД(М, N) = НОД(М - N, N)». Докажем правило. Пусть, K - один из общих делителей двух чисел, а m и n - числа, на которые умножается K, то M = mK, N = nK. Следовательно:
- M - N = mK - nK
- M - N = K(m - n)
Выводим a, так как a == b после последней итерации цикла.def NOK(a, b): while a != b: if a > b: a = a - b else: b = b - a return a
Выборка элементов
[править]Пусть, a - список, состоящий из чисел. Следует выбрать только те числа, которые лежат в диапазонах: [1; 10], [21; 30] и т. д. Количество интервалов определяется переменной inters.
def Get(a, inters):
for i in range(len(a)):
for j in range(i + 1, len(a)):
if a[j - 1] > a[j]:
a[j], a[j - 1] = a[j - 1], a[j]
i = 1
count = 0
while i <= inters*20:
j = 0
while (j < len(a)) and (a[j] <= i + 9):
if (a[j] >= i) and (a[j] <= i + 9):
count += 1
j += 1
i += 20
return count
Сортируем список для того, чтобы не выполнять во второй группе циклов лишние итерации.
Удаление элементов
[править]Пусть, есть список a, из которого надо удалить n элементов, начиная с i-ого элемента. Код удаления элементов будет следующий:
def Delete(a, i, n):
b = []
for i2 in range(0, len(a)):
b.append(a[i2])
for i2 in range(i, len(b) - n):
b[i2] = b[i2 + n]
return ''.join(b)[:len(b) - n:]
Сортировка по алфавиту
[править]Пусть, a - список, который следует отсортировать по алфавиту. Алгоритм:
- Создать список, определяющий номер каждой первой буквы каждой строки в алфавите.
- Отсортировать два списка.
def SortList(a):
alph = 'abcdefgijklmnopqrstuvwxyz'
b = []
for s in a:
i = 0
while s[0].lower() != alph[i]:
i += 1
b.append(i)
for i in range(0, len(a)):
for j in range(i + 1, len(a)):
if b[i] > b[j]:
b[i], b[j] = b[j], b[i]
a[i], a[j] = a[j], a[i]
return a
Вариант с кэшированием уже найденных символов:
def SortList(a):
alph = 'abcdefgijklmnopqrstuvwxyz'
K = {}
b = []
for s in a:
i = 0
try:
b.append(K[s[0]])
except KeyError:
while s[0].lower() != alph[i]:
i += 1
K[s[0]] = alph[i]
b.append(i)
for i in range(0, len(a)):
for j in range(i + 1, len(a)):
if b[i] > b[j]:
b[i], b[j] = b[j], b[i]
a[i], a[j] = a[j], a[i]
return a
Сортировка словаря
[править]Сам словарь отсортировать невозможно напрямую.
def SortList(d):
a = d.keys()
alph = 'abcdefgijklmnopqrstuvwxyz'
b = []
for s in a:
i = 0
while s[0].lower() != alph[i]:
i += 1
b.append(i)
for i in range(0, len(a)):
for j in range(i + 1, len(a)):
if b[i] > b[j]:
b[i], b[j] = b[j], b[i]
a[i], a[j] = a[j], a[i]
return a
Поиск подстроки
[править]def Find(Str, substr):
k = 0 # Количество равных символов.
if (len(Str) > len(substr)) and (len(substr) != 0):
for i in range(0, len(Str) - len(substr) + 1):
if k != len(substr):
for j in range(0, len(substr)):
if substr[j] != Str[j + i]:
break
else:
k += 1
if k == len(substr):
return i
else:
k = 0
return -1
else:
return -1
Поиск подстроки по шаблону
[править]Для каждого символа строки Str мы задаем список допустимых для него значений.
def Find(Str, patternL):
k = 0 # Количество равных символов.
if (len(Str) > len(patternL)) and (len(patternL) != 0):
for i in range(0, len(Str) - len(patternL) + 1):
if k != len(patternL):
for j in range(0, len(patternL)):
if not Str[j + i] in patternL[j]:
break
else:
k += 1
if k == len(patternL):
return i
else:
k = 0
return -1
else:
return -1
Пример использования:
Find('a1b324a2b124',[['a', 'b'], ['1']])
Удаление подстроки
[править]- В условии «(len(Str) > len(substr)) and (len(substr) != 0)» не пишем «and (len(Str) != 0)», так как часть условия «len(Str) > len(substr)» исключает это условие.
- i меняется от 0 до суммы разности длин строк и единицы, так как последнее значение в функции «range(0, len(Str) - len(substr) + 1)» не включается.
def DeleteSubstr(Str, substr):
k = 0 # Количество равных символов.
if (len(Str) > len(substr)) and (len(substr) != 0):
for i in range(0, len(Str) - len(substr) + 1):
if k != len(substr):
for j in range(0, len(substr)):
if substr[j] != Str[j + i]:
break
else:
k += 1
if k == len(substr):
b = []
for i2 in range(0, len(Str)):
b.append(Str[i2])
for i2 in range(i, len(Str) - len(substr)):
b[i2] = b[i2 + len(substr)]
return ''.join(b)[:len(b) - len(substr):]
else:
k = 0
return -1
else:
return -1
def DeleteSubstrs(Str, substr):
k = 0 # Количество равных символов.
if (len(Str) > len(substr)) and (len(substr) != 0):
for i in range(0, len(Str) - len(substr) + 1):
if k != len(substr):
for j in range(0, len(substr)):
if substr[j] != Str[j + i]:
break
else:
k += 1
if k == len(substr):
b = []
for i2 in range(0, len(Str)):
b.append(Str[i2])
for i2 in range(i, len(Str) - len(substr)):
b[i2] = b[i2 + len(substr)]
Str = ''.join(b)[:len(b) - len(substr):]
else:
k = 0
return Str
else:
return -1
def DeleteSubstrs(Str, substr):
s = Str
while DeleteSubstr(s, substr) != -1:
s = DeleteSubstr(s, substr)
return s
Поиск корня
[править]Нахождение квадратного корня:
import math
def Sqrt(x):
a = 0.5*x
if
while math.floor(a**2) != x:
if a**2 > x:
a = a*0.5
elif a**2 < x:
a = a*1.5
return a
Нахождение корня n-ной степени:
import math
def Sqrt(x, n):
a = 0.5*x
while math.floor(a**n) != x:
if a**n > x:
a = a*0.5
elif a**n < x:
a = a*1.5
return a
Четность и нечетность элемента в списке
[править]Индекс, с которого начинается отсчет | Формула для нечетных элементов | Формула для четных элементов |
---|---|---|
четный | индекс % 2 == 0 | индекс % 2 != 0 |
нечетный | индекс % 2 != 0 | индекс % 2 == 0 |
- Если считать от четного индекса, то у нечетных элементов будут четные индексы, а у четных - нечетные.
- Если считать от нечетного индекса, то у нечетных элементов будут нечетные индексы, а у четных - четные.