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 |
- Если считать от четного индекса, то у нечетных элементов будут четные индексы, а у четных - нечетные.
- Если считать от нечетного индекса, то у нечетных элементов будут нечетные индексы, а у четных - четные.