distance = sqrt((x-dropx)**2+(y-dropy)**2)
height = damping*a*exp(-(distance-
position_of_maximum)**2/c)* \
cos(freq*(distance-position_of_maximum))
Здесь,
Эффекты от многих брошенных капель в разное время и в разных позициях можно просто вычислить суммированием результирующих высот.
Единственная капля - это, конечно, не дождь, так что мы хотели бы видеть сложенные эффекты от множества случайных капель. Следовательно, мы должны выбирать произвольные позиции и время ударов для стольких капелек, сколько мы хотели бы сымитировать.
Мы должны были бы делать это каждый раз при вызове метода
К счастью, мы можем сохранить эти результаты в качестве экземпляров переменных нашего Pynode. Конечно, мы должны быть достаточно осторожными, чтобы проверять, что никакие входные параметры не были изменены между вызовами
class MyNode(Node.Scripted):
def __init__(self, sockets):
sockets.input = [Node.Socket('InputParam',
val = 1.0)]
sockets.output = [Node.Socket('OutputVal' ,
val = 1.0)]
self.InputParam = None
self.Result = None
def __call__(self):
if self.InputParam == None or \
self.InputParam != self.input.InputParam :
self.InputParam = self.input.InputParam
self.Result = интенсивные_вычисления ...
self.output.OutputVal = другие_вычисления …
Этот образец работает, только если входной параметр изменяется редко, например, только если его изменяет пользователь. Если вход изменяется с каждым пикселем, поскольку входной сокет подключен к выходу другого нода - схема с запоминанием, наоборот, будет дороже по времени вместо какой-либо экономии.
Нашей целью будет сгенерировать волновой узор, который можно использовать в качестве нормали. Так что нам нужен некий способ получить нормаль из рассчитанных высот. Блендер не предоставляет нам такого преобразующего нода для материалов, так что мы должны разработать схему самостоятельно.
Теперь, как и в случае ряби, мы могли бы, в принципе, вычислить также точную нормаль для нашей капли дождя, но, вместо движения по математическому пути, мы снова применяем метод, используемый многими встроенными текстурами шума для вычисления нормалей, который работает независимо от основной функции.
Пока мы можем оценивать функцию в трех точках:
Взяв все эти идеи из предыдущих параграфов, мы можем приготовить следующую программу для нашего Pynode Raindrops (с опущенными операторами
class Raindrops(Node.Scripted):
def __init__(self, sockets):
sockets.input = [
Node.Socket('Drops_per_second' ,
val = 5.0, min = 0.01, max = 100.0),
Node.Socket('a',val=5.0,min=0.01,max=100.0),
Node.Socket('c',val=0.04,min=0.001,max=10.0),
Node.Socket('speed',val=1.0,min=0.001, max=10.0),
Node.Socket('freq',val=25.0,min=0.1, max=100.0),
Node.Socket('dampf',val=1.0,min=0.01, max=100.0),
Node.Socket('Coords', val = 3*[1.0])]
sockets.output = [