Ir para conteúdo
Entre para seguir isso  
Eventide

particles

Recommended Posts

Eventide    7
Eventide

Tentei fazer um sistema de particles, mas não deu muito certo por dois motivos:

 

1° lento pra kct

2° nada funciona do jeito como eu imagino

 

Alguém poderia me ajudar?

 

Fiz usando Lua + LuaGL:

 

require("iuplua")
require("iupluagl")
require("luagl")
require("luaglu")
require("LoadTGA")
texture = {0, 0}

iup.key_open()

cnv = iup.glcanvas{buffer="DOUBLE", rastersize = "800x600"}

timer = iup.timer{time=2000}

currentParticle = nil

function timer:action_cb()
 iup.Update(cnv)
end

function cnv:resize_cb(width, height)
iup.GLMakeCurrent(self)
gl.Viewport(0, 0, width, height)

gl.MatrixMode('PROJECTION')   -- Select The Projection Matrix
gl.LoadIdentity()             -- Reset The Projection Matrix

if height == 0 then height = 1 end       -- Avoid division by zero
glu.Perspective(80, width / height, 1, 10000) -- Calculate The Aspect Ratio And Set The Clipping Volume

gl.MatrixMode('MODELVIEW')    -- Select The Model View Matrix
gl.LoadIdentity()             -- Reset The Model View Matrix
end

particles = {}

function createNewParticle(_active, _life, _fade, _rgb, _pos, _direction, _gravity)
table.insert(particles, {active = _active, life = _life, fade = _fade, rgb = _rgb, pos = _pos, direction = _direction, gravity = _gravity})
end

socket = require('socket') -- apenas para aliviar o processador

function rc()
return math.random(1, 10)/10
end

function createBreathParticles(dir, frompos, topos)
particles = {}
n = 100
life = 1
fade = 0.0001
z = -30
if dir == 1 then -- horizontal
	for t = 1, n do
		for x  = frompos[1], topos[1] do
			for y = frompos[2], topos[2] do
				createNewParticle(true, life, fade, {rc(), rc(), rc()}, {0, 0, z}, {x, y, 0}, {0, 0, 0})
				socket.sleep(0.0001)
			end

		end
		print('particles loading '.. t ..'%')
	end
elseif dir == 2 then -- vertical
	for t = 1, n do
		for y = frompos[2], topos[2] do
			for x = frompos[1], topos[1] do
				createNewParticle(true, life, fade, {1, 1, 1}, {0, 0, z}, {x, y, 0}, {0, 0, 0})
			end
		end
		print('particles loading '.. t ..'%')
	end
elseif dir == 3 then -- horizontal + vertical
	for t = 1, n do
		for y = frompos[2], topos[2] do
			for x = frompos[1], topos[1] do
				createNewParticle(true, life, fade, {1, 1, 1}, {0, 0, z}, {x, y, 0}, {0, 0, 0})
			end
		end
		for x  = frompos[1], topos[1] do
			for y = frompos[2], topos[2] do
				createNewParticle(true, life, fade, {1, 1, 1}, {0, 0, z}, {x, y, 0}, {0, 0, 0})
			end
		end
		print('particles loading '.. t ..'%')
	end
else
	return false
end
end

--function createNewParticle(_active, _life, _fade, _rgb, _pos, _direction, _gravity)
function createRisingStarsParticles()
n = 10
z = -30
math.randomseed(os.time())
while n >= 1 do
	n = n-1
	createNewParticle(true, 1, 0.3, {0.5, 0, 1}, {0, 0, z}, {math.random(-5, -3), 0, 0}, {0, 0 ,0})
end
n = 10
while n >= 1 do
	n = n-1
	createNewParticle(true, 1, 0.3, {1, 0.1, 1}, {0, 0, z}, {math.random(1, 5), 0, 0}, {0, 0 ,0})
end
n = 10
while n >= 1 do
	n = n-1
	createNewParticle(true, 1, 0.3, {0.3, 0.1, 0.8}, {0, 0, z}, {0, math.random(3, 5), 0}, {0, 0 ,0})
end

n = 10
while n >= 1 do
	n = n-1
	createNewParticle(true, 1, 0.5, {1, 0.1, 1}, {0, 0, z}, {0, math.random(-5, -1), 0}, {0, 0 ,0})
end
n = 10
while n >= 1 do
	n = n-1
	createNewParticle(true, 1, 0.3, {1, 0.1, 1}, {0, 0, z}, {math.random(3, 5), 5, 0}, {0, 0 ,0})
end
n = 10
while n >= 1 do
	n = n-1
	createNewParticle(true, 1, 0.3, {0.5, 0, 1}, {0, 0, z}, {-10, math.random(-10, -5), 0}, {0, 0 ,0})
end
n = 10
while n >= 1 do
	n = n-1
	createNewParticle(true, 1, 0.3, {1, 0.1, 1}, {0, 0, z}, {math.random(1, 5), -10, 0}, {0, 0 ,0})
end
n = 10
while n >= 1 do
	n = n-1
	createNewParticle(true, 1, 0.5, {0.3, 0.1, 0.8}, {0, 0, z}, {5, math.random(3, 6), 0}, {0, 0 ,0})
end
n = 10
while n >= 1 do
	n = n-1
	createNewParticle(true, 1, 0.3, {1, 0.1, 1}, {0, 0, z}, {math.random(-5, -3), -10, 0}, {0, 0 ,0})
end
n = 10
while n >= 1 do
	n = n-1
	createNewParticle(true, 1, 0.3, {1, 0.1, 1}, {0, 0, z}, {3, math.random(1, 5), 0}, {0, 0 ,0})
end	while n >= 1 do
	n = n-1
	createNewParticle(true, 1, 0.3, {0.5, 0, 1}, {0, 0, z}, {math.random(-5, -3), 0, 0}, {0, 0 ,0})
end
n = 10
while n >= 1 do
	n = n-1
	createNewParticle(true, 1, 0.3, {1, 0.1, 1}, {0, 0, z}, {math.random(1, 5), 0, 0}, {0, 0 ,0})
end
n = 10
while n >= 1 do
	n = n-1
	createNewParticle(true, 1, 0.3, {0.3, 0.1, 0.8}, {0, 0, z}, {0, math.random(3, 5), 0}, {0, 0 ,0})
end

n = 10
while n >= 1 do
	n = n-1
	createNewParticle(true, 1, 0.5, {1, 0.1, 1}, {0, 0, z}, {0, math.random(-5, -1), 0}, {0, 0 ,0})
end
n = 10
while n >= 1 do
	n = n-1
	createNewParticle(true, 1, 0.3, {1, 0.1, 1}, {0, 0, z}, {math.random(3, 5), 5, 0}, {0, 0 ,0})
end
n = 10
while n >= 1 do
	n = n-1
	createNewParticle(true, 1, 0.3, {0.5, 0, 1}, {0, 0, z}, {-10, math.random(-10, -5), 0}, {0, 0 ,0})
end
n = 10
while n >= 1 do
	n = n-1
	createNewParticle(true, 1, 0.3, {1, 0.1, 1}, {0, 0, z}, {math.random(1, 5), -10, 0}, {0, 0 ,0})
end
n = 10
while n >= 1 do
	n = n-1
	createNewParticle(true, 1, 0.5, {0.3, 0.1, 0.8}, {0, 0, z}, {5, math.random(3, 6), 0}, {0, 0 ,0})
end
n = 10
while n >= 1 do
	n = n-1
	createNewParticle(true, 1, 0.3, {1, 0.1, 1}, {0, 0, z}, {math.random(-5, -3), -10, 0}, {0, 0 ,0})
end
n = 10
while n >= 1 do
	n = n-1
	createNewParticle(true, 1, 0.3, {1, 0.1, 1}, {0, 0, z}, {3, math.random(1, 5), 0}, {0, 0 ,0})
end

end

function cnv:action(x, y)
iup.GLMakeCurrent(self)
gl.Clear('COLOR_BUFFER_BIT,DEPTH_BUFFER_BIT')
for k,v in pairs(particles) do
print(k.. 'of '.. #particles)

	x = v.pos[1]
	y = v.pos[2]
	z = v.pos[3]
	gl.Color(v.rgb[1], v.rgb[2], v.rgb[3], v.life);
	gl.Begin('TRIANGLE_STRIP')
		-- Top Right
		gl.TexCoord(1,1);
		gl.Vertex(x+0.5,y+0.5, z); 
		gl.TexCoord(0,1); 
		gl.Vertex(x-0.5,y+0.5, z); -- Top Left
		gl.TexCoord(1,0); 
		gl.Vertex(x+0.5, y-0.5, z); -- Bottom Right
		gl.TexCoord(0,0);
		gl.Vertex(x-0.5,y-0.5, z); -- Bottom Left
	gl.End()
	v.pos[1] = v.pos[1]+(v.direction[1])
	v.pos[2] = v.pos[2]+(v.direction[2])
	v.pos[3] = v.pos[3]+(v.direction[3])
	v.direction[1] = v.direction[1]+v.gravity[1]
	v.direction[2] = v.direction[2]+v.gravity[2]
	v.direction[3] = v.direction[3]+v.gravity[3]
	v.life = v.life-v.fade
	if v.life < 0 then
		v.life = 1
		v.pos = {0, 0 ,0}
	end
	socket.sleep(0.0001)
	iup.GLSwapBuffers(self)
end
end

function cnv:k_any(c)
if c == iup.K_q or c == iup.K_ESC then
	return iup.CLOSE
elseif c == iup.K_F1 then
	if fullscreen then
		fullscreen = false
		dlg.fullscreen = "No"
	else
		fullscreen = true
		dlg.fullscreen = "Yes"
	end
end
end

function LoadGLTextures()
texture[1] = gl.GenTextures(1)  -- Create The Texture

-- Typical Texture Generation Using Data From The Bitmap
gl.BindTexture('TEXTURE_2D', texture[1][1])
gl.TexParameter('TEXTURE_2D','TEXTURE_MIN_FILTER','LINEAR')
gl.TexParameter('TEXTURE_2D','TEXTURE_MAG_FILTER','LINEAR')
gl.TexEnv('BLEND', {0, 0, 0, 0})

img, err = LoadTGA('particle.tga')
if err then print(err) end

gl.TexImage(0, img)
end

function cnv:map_cb()
iup.GLMakeCurrent(self)
gl.Enable('TEXTURE_2D')            -- Enable Texture Mapping ( NEW )
LoadGLTextures()
createBreathParticles(1, {0, 0}, {10, 5})
gl.ShadeModel('SMOOTH')            -- Enable Smooth Shading
gl.ClearColor(0, 0, 0, 0.5)        -- Black Background
gl.ClearDepth(1.0)                 -- Depth Buffer Setup
gl.Disable('DEPTH_TEST')            -- Enables Depth Testing
gl.Enable('BLEND')
gl.BlendFunc('SRC_ALPHA', 'ONE')
gl.Hint('PERSPECTIVE_CORRECTION_HINT','NICEST') -- Really Nice Perspective Calculations
gl.Hint('POINT_SMOOTH_HINT', 'NICEST')           -- Really Nice Point Smoothing
gl.Enable('COLOR_MATERIAL')
gl.Hint('PERSPECTIVE_CORRECTION_HINT','NICEST')
end

dlg = iup.dialog{cnv; title="Particles testing"}

dlg:show()
cnv.rastersize = nil -- reset minimum limitation

timer.run = "YES"

if (not iup.MainLoopLevel or iup.MainLoopLevel()==0) then
iup.MainLoop()
end 

 

Na função createBreathParticles, por exemplo, era pra ser feito um movimento que começasse em determinada posição e fosse se expandindo tanto no eixo x quanto no y, mas o que acontece é um movimento totalmente aleatório, enquanto a função createRisingStarsParticles, na verdade era pra ser uma explosão, mas acabei criando outro feito um pouco mais tosco mas que eu acho que dá pra usar se mexer um pouco, por isso mudei o nome e desisti da explosão.

 

obs: não vai rodar sem o arquivo LoadTGA.lua que fica na pasta de exemplos do LuaGL.

obs²: fiz seguindo o tutorial do NeHe: http://nehe.gamedev.net/tutorial/particle_engine_using_triangle_strips/21001/

 

 

edit: coloquei o gl.Clear antes do for e deu merda, a textura passa a não funcionar... Mas deu pra ver que está funcionando quase da forma como eu quero, o único problema é que tanto a direção, quanto o life e o fade não tem efeito se o clear não for feito antes do loop...

edit²: coloquei alguns prints e percebi que a demora pra carregar é meio estranha, além de ser por colocar as partículas na tabela, ele itera por todas as particulas antes de começar a desenhá-las, e a cada nova iteração a área fica maior... Eu até poderia entender o porque se a gravidade não fosse 0...

Editado por Eventide

Compartilhar este post


Link para o post
Compartilhar em outros sites
Gpwjhlkdcf    21
Gpwjhlkdcf

É claro que vai ficar lento com os socket.sleep... Pode não ser isso, claro, mas quem diabos reclama de travamento em um código que usa uma função que diz claramente "trave meu programa" dentro de bilhões de loops?

Compartilhar este post


Link para o post
Compartilhar em outros sites
sequeled    0
sequeled

Concordo Skyen,

obiviamente ficara lento o code executa muitos loops 'while' para a mesma função.

É necessário um bom aproveitamento do loop vc faz muitos loops quase iguais...

Sem contar com os sleeps.

Tente jogar tudo dentro do mesmo loop.

Se a condição do while é n>=1 em todos não tem necessidades vc criar outros, melhore seu código diminua os loops talvez oque vc quer fazer use menos de 5 linhas.

Compartilhar este post


Link para o post
Compartilhar em outros sites
Eventide    7
Eventide

@skyen

O socket.sleep foi justamente pra tentar desafogar o processador, não fez diferença alguma no "efeito", mesmo com esses sleeps, meu processador chega a quase 100% rodando isso...

 

@sequeled

tem diferença em fazer 10 fors de 1 a 10 e 1 for de 1 a 100 com 10 ifs?

Compartilhar este post


Link para o post
Compartilhar em outros sites
Conde2    0
Conde2

XXXXX

Editado por Conde2

Compartilhar este post


Link para o post
Compartilhar em outros sites
Eventide    7
Eventide

eu mudei o iup.time de 100 pra 2000 pra tentar desafogar o processador, mas não deu muito certo... =|

 

e eu não entendi o porque da iteração ser feita com pairs faz ficar tudo aleatório, você poderia explicar melhor isso?

Compartilhar este post


Link para o post
Compartilhar em outros sites
Conde2    0
Conde2

XXXXX

Editado por Conde2

Compartilhar este post


Link para o post
Compartilhar em outros sites
Gpwjhlkdcf    21
Gpwjhlkdcf

pairs não é aleatório, ele acessa na ordem que está armazenado na memória, o que nem sempre é o que você quer. Se quer ordem, use ipairs com índices numéricos, porque o pairs não entende ordem alfabética pra índices de string. À não ser que você use um table.sort antes.

 

Em alto nível, não tem diferença fazer 100 fors de 1 à 1 ou 1 for de 1 à 100, mas em baixo nível são mais instruções à serem interpretadas, então tem influência sim.

 

E para com essa frescura de desafogar o processador. Isso não é do seu programa, isso é da própria linguagem Lua, se não quer 100% de ocupação da CPU use outra linguagem.

 

Tire os prints, prints são lentos.

Tire os sleeps.

Junte os loops.

 

table.insert é mais eficiente por ser uma única operação à ser interpretada, particles[#particles + 1] utiliza três: acesso, soma e atribuição. Ela também é mais eficiente quando precisa inserir um valor no meio da tabela reposicionando vários valores.

Compartilhar este post


Link para o post
Compartilhar em outros sites
Conde2    0
Conde2

XXXXX

Editado por Conde2

Compartilhar este post


Link para o post
Compartilhar em outros sites
Eventide    7
Eventide

table.insert é mais eficiente por ser uma única operação à ser interpretada, particles[#particles + 1] utiliza três: acesso, soma e atribuição. Ela também é mais eficiente quando precisa inserir um valor no meio da tabela reposicionando vários valores.

Foi um ótimo post até essa parte... Leia:

http://springrts.com/wiki/Lua_Performance#TEST_12:_Adding_Table_Items_.28table.insert_vs._.5B_.5D.29

 

Depois de ler isso eu passei a fazer assim:

local table = table
function table.insert(t, i)
local a = #t + 1
t[a] = i
return a
end

fez uma diferença boa viu...

Editado por Eventide

Compartilhar este post


Link para o post
Compartilhar em outros sites
Gpwjhlkdcf    21
Gpwjhlkdcf
Foi um ótimo post até essa parte... Leia:

http://springrts.com/wiki/Lua_Performance#TEST_12:_Adding_Table_Items_.28table.insert_vs._.5B_.5D.29

 

Depois de ler isso eu passei a fazer assim:

local table = table
function table.insert(t, i)
local a = #t + 1
t[a] = i
return a
end

fez uma diferença boa viu...

 

Que interessante, alguém sabe o motivo? Na teoria, são duas operações a mais à serem executadas. Imagino que os operadores de Lua sejam implementados inline, enquanto a table.insert precisa ser chamada no sistema.

 

De qualquer forma, isso só serve pra tabelas sequenciais, então depende da situação.

Compartilhar este post


Link para o post
Compartilhar em outros sites
Conde2    0
Conde2

XXXXX

Editado por Conde2

Compartilhar este post


Link para o post
Compartilhar em outros sites

Faça login para comentar

Você vai ser capaz de deixar um comentário após fazer o login



Entrar Agora
Entre para seguir isso  

  • Quem Está Navegando   0 membros estão online

    Nenhum usuário registrado visualizando esta página.

×