2011-10-04 20 views
32

Ho cercato su Google per questo, ma non ci sono script pronti, a differenza dello stesso effetto su Flash. Ho controllato l'algoritmo su The Water Effect Explained e testato anche un'implementazione dello Perlin Noise, che fornisce una buona simulazione della fine delle onde su una superficie piana. Sto cercando la stessa implementazione trovata su diversi effetti Flash, basata su azioni mouseover/hover. Si tratta di una libreria di pavimento interattiva, e mi piacerebbe allontanarmi da Flash per questo, in particolare per evitare un così semplice reverse-engineering del codice - e sì, so che potrebbe usare solo un codice flash già pronto, ma io lo userei solo come ultima risorsa.Effetto ripple dell'acqua Pygame

Qualcuno ha visto un'adeguata implementazione di questo effetto per Pygame (usando OpenGL o no)?

MODIFICA: Qualcuno può fornire un'adeguata implementazione di questo effetto utilizzando OpenCV/OpenGL e Pygame?

Il colpevole è l'interfaccia (di codice) per passare un elenco di valori che verrà inviato da un interprete esterno (tracker - non TUIO) tramite Python. Ho provato per alcuni giorni consecutivi, ma Pygame non è in grado di generare nulla veloce come puro codice C/C++ (come usato per gli shader in OpenGL), e la mia conoscenza di C/C++ è nullo. Quindi l'obiettivo è di avere almeno quello proveniente dal codice Python.

Un buon esempio, diverso dall'effetto Flash, ma che è ancora buono è Water Simulation using Java applet.

(la bounty sta mostrando le risposte non hanno abbastanza dettagli dato che questo era il più vicino a "l'OP non è in grado di creare il codice che vuole dato che manca di abilità fondamentali e questa risposta sarà probabilmente utile a più persone") .

+1

è questo quello che vuoi che funzioni? http://flash-effects.com/tutorial-create-a-water-ripple-mouse-follow/ – misha

+0

esattamente - se ciò è possibile, naturalmente posso procedere con il tweaking – leon

+1

Potrebbe anche voler provare gamedev.stackexchange. com, potrebbe avere migliore fortuna lì. – Davy8

risposta

8

Dopo d oing compiti (a.k.a.ricerca) e cercando di convertire direttamente il riferimento al codice Java pubblicato sulla domanda in Python, e avendo un'esperienza molto, molto triste mentre si prova ad avere Python/Numpy aggiornare una serie enorme di pixel in base alle loro posizioni per l'increspatura del ripple effetto (mi dispiace, la mia prima lingua non è l'inglese), quindi analizzando diverse posizioni (x, y) per ogni passaggio dei calcoli dell'effetto e facendo un bling sulla superficie visualizzata sullo schermo (deriva il surfarray), sono arrivato al conclusione - sostenuta da altri commentatori - che Pygame semplicemente non sia sufficientemente potente da attraversare effettivamente l'intera serie di pixel e applicare risultati di calcoli su ogni pixel sullo schermo ad una velocità minima di 24 fps (per un esperienza inferiore alla media).

Citando il molto sviluppatore dietro Last Light Productions e l'ex Project Geometrian, Ian Mallet:

PyGame non è così buono per pixel spingere. Niente è, oltre alla GPU.

La ricerca poi si rivelò essere una ricerca di Alkahest - qualcosa che risulterebbe non essere mai veramente trovato - e sulla base della stessa idea di increspatura immagini, ma questa volta utilizzando la trasparenza di vedere attraverso diversi strati di superfici di Pygame, ho postato la domanda Pygame circular cropping/masks su Gamedev. Lo chosen answer in realtà corrobora il fatto che temevo già che Pygame non sarebbe mai stato macho abbastanza per il lavoro.

Un giorno dopo sono tornato alle mie idee precedenti sullo sviluppo e ho trovato Ogre3D. Si scopre che (1) Ogre3D e gli esempi sono open-source e (2) uno degli esempi è un modello d'acqua 3-D che interagisce con un oggetto in movimento, esattamente la stessa cosa che ho cercato di ottenere in 2-D, ma in un modo molto più professionale.

Dal momento che la mia conoscenza in C/C++ è pari a zero, ho deciso di chiedere how to customize the Ogre3D water demo per un assaggio di dove cominciare a guardare, e una delle risposte mi ha segnalato il software da Touchscape in cui viene fornito uno SDK (vedi this answer).

Ogre3D praticamente lo ha avvolto. effetto a catena Acqua, OpenGL (che può optionally uso basata su hardware), Game Engine e Python wrapper tramite Python-Ogre - quindi la mia risposta alla mia domanda,

Qualcuno può fornire un adeguato implementazione di questo effetto utilizzando OpenCV/OpenGL e Pygame?

è fondamentalmente

Sì. Controlla la demo dell'acqua di Ogre3D, fornita con l'SDK - e collegala a Python tramite Python-Ogre.

5

Il seguente utilizzo di numpy potrebbe iniziare. Dovrebbe essere abbastanza veloce in quanto è possibile ottenere molto più velocemente anche in python (dai un'occhiata qui per vedere come http://www.scipy.org/PerformancePython).

proposito esistono diversi inconvenienti nel metodo descritto:

  1. non si può controllare la velocità delle increspature - per farlo sarebbe necessario modificare le equazioni utilizzate nella funzione ripple (se si figura come si relaziona all'equazione delle onde http://en.wikipedia.org/wiki/Wave_equation poi hai finito)
  2. la "profondità" del "pool" è fissa (e probabilmente troppo bassa). Ho aggiunto un parametro di profondità per ingrandire l'effetto
  3. l'articolo legge i pixel interi offset - otterresti un risultato molto più bello con valori interpolati (credo che tu possa farlo con opengl, ma la mia conoscenza in quell'area è nulla)

codice:

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) 

xey devono essere griglie da una chiamata numpy.meshgrid: qui un esempio dell'uso:

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) #