Pertanyaan Efek riak air pygame


Saya telah Googled untuk itu tetapi tidak ada skrip siap - sebagai lawan dari efek yang sama pada Flash. Saya telah memeriksa algoritma tersebut The Water Effect Dijelaskan dan juga menguji implementasi Perlin Noise, yang memberikan simulasi yang baik dari ujung gelombang pada permukaan yang datar. Saya mencari implementasi yang sama yang ditemukan pada beberapa Efek Flash, berdasarkan gerakan gerakan mouse / mouse. Ini menargetkan perpustakaan lantai interaktif, dan saya akan senang bergerak menjauh dari Flash untuk masalah ini, terutama untuk menghindari rekayasa ulang kode yang mudah - dan ya, saya tahu itu hanya bisa menggunakan beberapa kode flash yang sudah jadi, tapi saya hanya akan menggunakannya sebagai jalan terakhir.

Adakah yang melihat implementasi yang cocok dari efek ini untuk Pygame (menggunakan OpenGL atau tidak)?

EDIT:  Adakah yang bisa memberikan implementasi yang sesuai dari efek ini menggunakan OpenCV / OpenGL dan Pygame?

Pelakunya di sini adalah antarmuka (kode) untuk memberikan daftar nilai yang akan dikirim dari interpreter eksternal (pelacak - bukan TUIO sekalipun) melalui Python. Saya telah mencoba selama beberapa hari berturut-turut tetapi Pygame tidak dapat menghasilkan apa pun secepat kode C / C ++ (seperti yang digunakan untuk shader dalam OpenGL), dan pengetahuan saya tentang C / C ++ adalah nol. Jadi targetnya adalah setidaknya memiliki kode Python.

Contoh yang bagus, berbeda dari efek Flash tetapi itu masih bagus Simulasi Air menggunakan applet Java.

(Bounty menunjukkan jawaban tidak memiliki cukup detail karena ini adalah yang paling dekat dengan 'OP tidak mampu menciptakan kode yang dia inginkan karena dia tidak memiliki keterampilan dasar dan jawaban ini mungkin akan berguna bagi beberapa orang').


32
2017-10-04 12:43


asal


Jawaban:


Setelah melakukan pekerjaan rumah (alias penelitian) dan mencoba untuk langsung mengubah referensi kode Java yang diposting pada pertanyaan menjadi Python, dan memiliki pengalaman yang sangat, sangat menyedihkan ketika mencoba untuk memiliki Python / Numpy memperbarui array warna pixel yang sangat banyak berdasarkan posisi mereka untuk riak dari efek riak (maaf, bahasa pertama saya bukan bahasa Inggris), sehingga menguraikan beberapa posisi (x, y) untuk setiap laluan dari perhitungan efek dan mengaburkannya ke permukaan yang ditampilkan di layar (surfarray terjadi), saya sudah sampai pada kesimpulan - yang didukung oleh komentator lain - bahwa Pygame sederhana biasa cukup kuat untuk benar-benar melintasi seluruh larik piksel dan menerapkan hasil perhitungan ke setiap piksel pada layar dengan laju minimum 24 fps (untuk pengalaman yang kurang dari rata-rata).

Mengutip pengembang di belakang Produksi Cahaya Terakhir dan yang pertama Proyek Geometrian, Ian Mallet:

PyGame tidak begitu bagus untuk mendorong piksel. Tidak ada apa-apa selain GPU.

Pencarian kemudian berubah menjadi pencarian Alkahest - sesuatu yang akan berubah tidak pernah benar-benar ditemukan - dan berdasarkan ide yang sama dari gambar beriak, tapi kali ini dengan menggunakan transparansi untuk tembus pandang beberapa lapisan permukaan Pygame, saya memposting pertanyaan Pygame circular cropping / masks di Gamedev. Itu jawaban yang dipilih sebenarnya menguatkan fakta yang sudah saya takutkan bahwa Pygame tidak akan pernah ada jantan cukup untuk pekerjaan itu.

Suatu hari kemudian saya kembali ke ide-ide saya sebelumnya tentang pengembangan dan menemukan Ogre3D. Ternyata (1) Ogre3D dan sampel adalah open-source dan (2) salah satu contohnya adalah model air 3-D yang berinteraksi dengan objek bergerak, persis sama dengan yang saya coba capai dalam 2-D, tetapi dengan cara yang jauh lebih profesional.

Karena pengetahuan saya di C / C ++ tidak ada, saya memutuskan untuk bertanya cara menyesuaikan demo air Ogre3D untuk melihat di mana untuk mulai mencari, dan salah satu jawaban mengarahkan saya ke perangkat lunak dari Touchscape tempat SDK disediakan (lihat jawaban ini).

Ogre3D cukup banyak membungkusnya. Efek riak air, OpenGL (yang mungkin secara opsional gunakan berdasarkan perangkat keras), Game Engine, dan Python wrappers via Python-Ogre - jadi jawaban saya untuk pertanyaan saya sendiri,

Adakah yang bisa memberikan implementasi yang sesuai dari efek ini menggunakan OpenCV / OpenGL dan Pygame?

pada dasarnya

Iya nih. Periksa demo air Ogre3D, yang disediakan dengan SDK - dan hubungkan ke Python via Python-Ogre.


8
2017-10-26 23:29



Berikut ini menggunakan numpy mungkin bisa Anda mulai. Ini harus cukup cepat karena meskipun Anda bisa mendapatkan lebih cepat bahkan dengan python (lihat di sini untuk melihat caranya http://www.scipy.org/PerformancePython).

By the way ada beberapa kelemahan dalam metode yang dijelaskan:

  1. Anda tidak dapat mengontrol kecepatan riak - untuk melakukan itu Anda harus memodifikasi persamaan yang digunakan dalam fungsi riak (jika Anda mengetahui bagaimana hubungannya dengan persamaan gelombang http://en.wikipedia.org/wiki/Wave_equation maka Anda selesai)
  2. "kedalaman" dari "kolam" adalah tetap (dan mungkin terlalu dangkal). Saya menambahkan parameter kedalaman untuk memperbesar efeknya
  3. artikel tersebut membaca offset piksel integer - Anda akan mendapatkan hasil yang jauh lebih bagus dengan nilai interpolasi (saya kira Anda dapat melakukannya dengan OpenGL, tetapi pengetahuan saya di area tersebut adalah nol)

kode:

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 dan y harus berupa grid dari panggilan numpy.meshgrid: ini contoh penggunaan:

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

5
2017-10-08 12:14