Particles optimization

Questions about the LÖVE API, installing LÖVE and other support related questions go here.
Forum rules
Before you make a thread asking for help, read this.
Mateus
Prole
Posts: 42
Joined: Sat Apr 04, 2015 1:02 pm

Re: Particles optimization

Post by Mateus »

Code: Select all

	require "mathlib"
io.stdout:setvbuf("no")
ScrH = 800
ScrW = 1000

particles = {}
pSize = 5

borders = {}
MinBorderDist = 20
MinCellDist = 10
MaxCellSpeed = 2

CellFriction = 600

Repell = 100
spawnTimer = 0

shader = love.graphics.newShader("shaders/glow.fs")

canvas = love.graphics.newCanvas(ScrW, ScrH, texture_type, fsaa)

function particlesUpdate(dt)
	if #particles > 0 then
		for k,v in pairs(particles) do
			v.pX = v.pX + v.pDirX
			v.pY = v.pY + v.pDirY

			if v.pX < MinBorderDist then
				v.pDirX = v.pDirX - (v.pX - MinBorderDist)/Repell
			end
			if v.pY < MinBorderDist then
				v.pDirY = v.pDirY - (v.pY - MinBorderDist)/Repell
			end
			if v.pX > (ScrW - MinBorderDist) then
				v.pDirX = v.pDirX - (v.pX - (ScrW -MinBorderDist) )/Repell
			end
			if v.pY > (ScrH - MinBorderDist) then
				v.pDirY = v.pDirY - (v.pY - (ScrH - MinBorderDist) )/Repell
			end

			for h,j in pairs(particles) do


				if h ~= k then
					local dist = vec2dist(j.pX,j.pY,v.pX,v.pY)
					
					if dist < MinCellDist then
						v.pDirX = v.pDirX - ( (j.pX-v.pX) ) / ((Repell/j.pMass)*(v.pMass - pSize ))
						v.pDirY = v.pDirY - ( (j.pY-v.pY) ) / ((Repell/j.pMass)*(v.pMass - pSize ))


					end


				end
			end

			v.pDirX = v.pDirX - (0 + (v.pDirX/CellFriction))
			v.pDirY = v.pDirY - (0 + (v.pDirY/CellFriction))

			v.pDirX = math.clamp(v.pDirX,-MaxCellSpeed,MaxCellSpeed)
			v.pDirY = math.clamp(v.pDirY,-MaxCellSpeed,MaxCellSpeed)

		end
	end
end

function particlesDraw()
	if #particles > 0 then
		for k,v in pairs(particles) do
			for h,j in pairs(particles) do


				if h ~= k then
					local dist = vec2dist(j.pX,j.pY,v.pX,v.pY)
					
					if dist < MinCellDist+j.pMass*2 then
						love.graphics.setColor(255,255,255,255-math.clamp((dist-j.pMass)*(MinCellDist/10),0,255) )
						love.graphics.line(v.pX,v.pY,j.pX,j.pY)
					end


				end
			end

			love.graphics.setColor(255,255,255,255)
			love.graphics.circle('fill',v.pX,v.pY,v.pMass)

		end
	end
end


function love.load()
	love.window.setMode(ScrW, ScrH,{vsync=false})

	rnd = love.math.newRandomGenerator(os.time())

end

function love.update(dt)

	love.window.setTitle('FPS: '..love.timer.getFPS())

	if love.mouse.isDown(1) then
		if spawnTimer <= 0 then

			spawnTimer = 8-dt

			for i=1,5 do
				if rnd:random(1,10) == 5 then
					mass = rnd:random(pSize+1,pSize+15)
				else
					mass = pSize+1
				end
				X = love.mouse.getX() + rnd:random(-100,100)/100
				Y = love.mouse.getY() + rnd:random(-100,100)/100
				table.insert(particles,{
					pX = X,
					pY = Y,
					pDirX = X - love.mouse.getX(),
					pDirY = Y - love.mouse.getY(),
					pMass = mass
				})
			end

		end
	end
	spawnTimer = spawnTimer - 1

	
	particlesUpdate(dt)


end

function love.draw()
	
	if #particles > 0 then
		particlesDraw()
	end
	
	love.graphics.setColor(255,255,255,255)
end
bobbyjones
Party member
Posts: 730
Joined: Sat Apr 26, 2014 7:46 pm

Re: Particles optimization

Post by bobbyjones »

It's probably slow cuz you are using pairs instead of ipairs.

Edit 1: after irc had their fun making fun of my response I realized that using ipairs might give you a again but a small one considering you are using C APIs in some of your loops. Using a mesh or a spritebatch may give you a larger gain.
User avatar
ivan
Party member
Posts: 1912
Joined: Fri Mar 07, 2008 1:39 pm
Contact:

Re: Particles optimization

Post by ivan »

The main problem is:

Code: Select all

for every particle
  for every other particle
This means, number of checks = n(n − 1)/2 where n is the number of particles
and the number blows up quickly.

This is a non-trivial problem that cannot be addressed reasonably without spatial partitioning.
Also, you're checking each pair twice, a common approach is to do:

Code: Select all

for i = 1, #particles do
  for j = i + 1, #particles do
Lastly you need to study up on locals a little bit.
In Lua, each time you write "mytable.a" you're doing a table lookup.
Attached is an alternative version. I've changed up some of your physics
code as I could not understand it. :)

You can change the "maxmass" variable to adjust how much
the velocity of adjacent particles is affected by gravity.
Damping affects how objects slow down on their own.

PS.A more clever solution might be to implement gravity in this case as a 'vector field'.
Attachments
particles.love
damping fix, modified the velocity of BOTH particles
(1.23 KiB) Downloaded 77 times
Post Reply

Who is online

Users browsing this forum: No registered users and 5 guests