Jump to content
  • Advertisement
Sign in to follow this  
Geometrian

Ripple Hack on Large Grids

This topic is 2339 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi,

Problem is: objects fall into a 2D tank, leaving 1D ripples.

I have implemented techniques similar to the technique best described here: http://freespace.virgin.net/hugo.elias/graphics/x_water.htm. Unfortunately, these quickly result in high frequency noise because of the initial discontinuity of perturbing a single particle. However, though the particles are oscillating, I can make out slow-moving waves. It's these slow-moving waves that I want!

Basically, I'm looking for a hackish algorithm that can generate plausible-looking waves on the surface of a 1D grid, using any detail level of grid.

I present the following Python code as a demonstration of the algorithm's faults, and as a testbed for new algorithms:[source lang="python"]import pygame
from pygame.locals import *
import sys, os, traceback
if sys.platform == 'win32' or sys.platform == 'win64':
os.environ['SDL_VIDEO_CENTERED'] = '1'
pygame.display.init()
pygame.font.init()
screen_size = [1200,200]
icon = pygame.Surface((1,1)); icon.set_alpha(0); pygame.display.set_icon(icon)
pygame.display.set_caption("1D Surface Test - Ian Mallett - v.1 - 2012")
surface = pygame.display.set_mode(screen_size)
num = 300
#====================================METHOD 1====================================
###My feeble algorithm
##class particle:
## def __init__(self):
## self.height = 0
## self.speed = 0
## self.force = 0
## def apply(self,force):
## self.force += 10*force
##def update():
## particles[0].force += -0.1*(particles[0].height-0.0)
## for i in xrange(1,num,1):
## particles.force += -0.1*(particles.height-particles[i-1].height)
##
## for i in xrange(0,num-1,1):
## particles.force += -0.1*(particles.height-particles[i+1].height)
## particles[-1].force += -0.1*(particles[-1].height-0.0)
##
## for i in xrange(0,num,1):
## particles.force += -0.1*(particles.height-0.0)
##
## for i in xrange(0,num,1):
## particles.speed += particles.force
## particles.speed *= 0.9999
## particles.height += particles.speed
## particles.force = 0
#====================================METHOD 2====================================
#Method after http://freespace.virgin.net/hugo.elias/graphics/x_water.htm
class particle:
def __init__(self):
self.buffer1 = 0.0
self.buffer2 = 0.0
self.height = 0.0
def apply(self,force):
self.buffer1 += 10*force
def update():
## kernel = 1
for i in xrange(1,num-1,1):
particles.buffer2 = (
particles[i-1].buffer1+
particles[i+1].buffer1
)/2.0 - particles.buffer2
## last = particles.buffer2
## particles.buffer2 = 0.0
## max_sum = 0.0
## for x in xrange(-kernel,kernel+1,1):
## index = i + x
## if index < 0: continue
## if index >= num: continue
## particles.buffer2 += particles[index].buffer1
## max_sum += 1.0
## particles.buffer2 /= max_sum
## particles.buffer2 -= last

particles.buffer2 *= 0.99999
particles.height = particles.buffer2
for i in xrange(0,num,1):
temp = particles.buffer2
particles.buffer2 = particles.buffer1
particles.buffer1 = temp
#====================================END METHODS====================================
def setup():
global particles, paused
particles = [particle() for x in xrange(num)]
paused = False
def get_input():
global paused
key = pygame.key.get_pressed()
for event in pygame.event.get():
if event.type == QUIT: return False
elif event.type == KEYDOWN:
if event.key == K_ESCAPE: return False
elif event.key == K_UP: particles[150].apply(10)
elif event.key == K_DOWN: particles[150].apply(-10)
elif event.key == K_p: paused = not paused
elif event.key == K_LEFT: update()
elif event.key == K_r: setup()
return True
def draw():
surface.fill((0,0,0))
points = []
x = 0
for particle in particles:
x += 4
points.append((x,particle.height+100))
pygame.draw.aalines(surface,(50,50,50),False,points)
i = 0
for point in points:
color = [(255,0,0),(0,255,0)][i%10==0]
pygame.draw.circle(surface,color,point,2,0)
i += 1

pygame.display.flip()
def main():
setup()
clock = pygame.time.Clock()
while True:
if not get_input(): break
if not paused: update()
draw()
clock.tick(60)
pygame.quit(); sys.exit()
if __name__ == '__main__':
try:
main()
except Exception, e:
tb = sys.exc_info()[2]
traceback.print_exception(e.__class__, e, tb)
pygame.quit()
raw_input()
sys.exit()[/source]After a few waves hit the tank, you get:
highfreq.png

So, can anyone suggest an algorithm? Or maybe some gaping flaw in my implementation?

Thanks!
Ian

Share this post


Link to post
Share on other sites
Advertisement
For 2d and 3d cases, solving the actual wave equation with the euler method isn't fast enough, but it might be for 1d! It's not hard to implement if you're familiar with the math.

Share this post


Link to post
Share on other sites
I've made a quick implementation with unity here and I didn't like it.. very hard to find the a suitable set or parameters to make the simulation behave properly. It's preytty fast though! My line has 50 points and it runs with more than a thousand fps. I used a damped wave equation and euler method. If you're interested I can give you the code.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!