Подтвердить что ты не робот

Эффект пульсации воды Pygame

У меня есть Googled для него, но нет готовых скриптов - в отличие от того же эффекта на Flash. Я проверил алгоритм на Объясненный водный эффект, а также протестировал реализацию Perlin Noise, который обеспечивает хорошее моделирование конца волн на плоской поверхности. Я ищу ту же реализацию, что и в нескольких Flash Effects, на основе действий mouseover/hover. Это нацелено на интерактивную библиотеку для пола, и мне было бы полезно уйти от Flash по этому поводу, в частности, чтобы избежать такой простой обратной обработки кода - и да, я знаю, что он может просто использовать какой-то готовый код флэш-памяти, но я будет использовать это только как последнее средство.

Кто-нибудь видел подходящую реализацию этого эффекта для Pygame (используя OpenGL или нет)?

EDIT: Может ли кто-нибудь обеспечить подходящую реализацию этого эффекта с помощью OpenCV/OpenGL и Pygame?

Виной здесь является (код) интерфейс, чтобы передать список значений, которые будут отправляться из внешнего интерпретатора (трекер - не TUIO, хотя) через Python. Я пробовал в течение нескольких дней, но Pygame не может генерировать ничего так же быстро, как чистый код C/С++ (как используется для шейдеров в OpenGL), и мои знания C/С++ равны нулю. Таким образом, цель состоит, по крайней мере, в том, что это происходит из кода Python.

Хороший пример, отличный от эффекта Flash, но который все еще хорош, Моделирование воды с использованием Java-апплета.

(у bounty есть ответы, у которых недостаточно деталей, поскольку это было самым близким к "OP неспособно создать код, который он хочет, поскольку ему не хватает фундаментальных навыков, и этот ответ, вероятно, будет полезен нескольким людям" ).

4b9b3361

Ответ 1

После выполнения домашней работы (ака-исследования) и попытки напрямую преобразовать ссылку на Java-код, размещенную на вопрос в Python, и иметь очень и очень грустный опыт при попытке обновления Python/Numpy массива пиксельных цветов, основанного на их позиции для рябь эффекта пульсации (извините, мой первый язык не является английским), таким образом анализируя несколько (x, y) позиций для каждого прохода вычислений эффекта и блуждающего, что на отображаемую поверхность на экране (всплывает навигация)), Я пришел к выводу, что подкрепляется другими комментаторами, - что Pygame просто не будет достаточно мощным, чтобы фактически пройти весь этот массив пикселей и применить результаты вычислений на каждый пиксель на экране с минимальной скоростью 24 кадра в секунду (для менее чем среднего опыта).

Цитата самого разработчика за Last Light Productions и предыдущий Project Geometrian, Ян Маллет:

PyGame не так хорош для нажатия на пиксель. Ничего нет, кроме графического процессора.

Затем поиск оказался поиском Alkahest - то, что не получилось бы действительно найти - и основано по той же идее рябь изображений, но на этот раз, используя прозрачность, чтобы увидеть несколько слоев поверхности Pygame, я разместил вопрос о круговой обрезке/масках Pygame на Gamedev. Выбранный ответ фактически подтверждает тот факт, что я уже опасался, что Pygame никогда не будет достаточно мачо для этой работы.

На следующий день я вернулся к своим предыдущим идеям развития и наткнулся на Ogre3D. Оказывается, что (1) Ogre3D и образцы являются open-source, и (2) одним из примеров является трехмерная модель воды, которая взаимодействует с движущимся объектом, точно так же, как я пытался достичь в 2D-режиме, но в гораздо более профессиональной манере.

Поскольку мои знания в C/С++ ноль, я решил спросить как настроить демонстрацию воды Ogre3D, чтобы увидеть, с чего начать, и один ответов указывал мне на программное обеспечение от Touchscape, где предоставляется SDK (см. этот ответ).

Ogre3D довольно сильно обернул его. Эффект пульсации воды, OpenGL (который может опционально использовать на основе аппаратного обеспечения), Game Engine и обертки Python через Python-Ogre - так что мой ответ на мой собственный вопрос,

Может ли кто-нибудь обеспечить подходящую реализацию этого эффекта с помощью OpenCV/OpenGL и Pygame?

в основном

Да. Проверьте демонстрационную демонстрационную версию Ogre3D, поставляемую с SDK, и подключите ее к Python через Python-Ogre.

Ответ 2

При использовании numpy вы можете начать работу. Он должен быть достаточно быстрым, поскольку он может быть намного быстрее даже в python (посмотрите здесь, как http://www.scipy.org/PerformancePython).

Кстати, в описанном методе есть несколько недостатков:

  • вы не можете контролировать скорость ряби - для этого вам придется изменить уравнения, используемые в функции пульсации (если вы выясните, как она относится к волновому уравнению http://en.wikipedia.org/wiki/Wave_equation, тогда вы закончите)
  • "глубина" "пула" фиксирована (и, вероятно, слишком мелкая). Я добавил параметр глубины, чтобы увеличить эффект.
  • в статье читаются смещения целочисленных пикселей - вы получите гораздо более приятный результат с интерполированными значениями (я думаю, вы можете сделать это с помощью opengl, но мои знания в этой области равны нулю)

код:

import numpy

def ripple(w1, w2, damp, n = 1):
    for _ in xrange(n):
        w2 *= -2
        w2[1:-1,1:-1] += w1[0:-2, 1: -1]
        w2[1:-1,1:-1] += w1[2:  , 1: -1]
        w2[1:-1,1:-1] += w1[1:-1, 0: -2]
        w2[1:-1,1:-1] += w1[1:-1, 2:   ]
        w2 *= .5 * (1. - 1./damp)
        w1, w2 = w2, w1

def refract(x, y, w, rindex, depth = 10):
    sx = x[0,1] - x[0,0]
    sy = y[1,0] - y[0,0]

    dw_dx = (w[2: ,1:-1] - w[:-2,1:-1]) / sx * .5
    dw_dy = (w[1:-1,2: ] - w[1:-1,:-2]) / sy * .5

    xang = numpy.arctan(dw_dx)
    xrefract = numpy.arcsin(sin(xang) / rindex)
    dx = numpy.tan(xrefract) * dw_dx * depth

    yang = numpy.arctan(dw_dy)
    yrefract = numpy.arcsin(sin(yang) / rindex)
    dy = numpy.tan(yrefract) * dw_dy * depth

    dx *= numpy.sign(dw_dx)
    dy *= numpy.sign(dw_dy)

    xmin = x[0,0]
    xmax = x[0,-1]
    x[1:-1,1:-1] += dx
    x[:,:] = numpy.where(x < xmin, xmin, x)
    x[:,:] = numpy.where(x > xmax, xmax, x)

    ymin = y[0,0]
    ymax = y[-1,0]
    y[1:-1,1:-1] += dy
    y[:,:] = numpy.where(y < ymin, ymin, y)
    y[:,:] = numpy.where(y > ymax, ymax, y)

x и y должны быть сетками из вызова numpy.meshgrid: здесь пример использования:

    x,y = meshgrid(x,y)
    w = 10 * exp(- (x*x + y*y))
    w1 = w.copy()
    x1,y1 = meshgrid(r_[0:len(x):1.0], r_[0:len(y):1.0])
    ripple(w, w1, 16) # w1 will be modified
    refract(x1, y1, w1, rindex=2, depth=10) # x1 and y1 will be modified
    numpy.around(x1, out=x1) # but you will get better results with interpolate
    numpy.around(y1, out=y1) #