Eventide 7 #1 Postado 22 Junho, 2013 (editado) 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 22 Junho, 2013 por Eventide Compartilhar este post Link para o post Compartilhar em outros sites
Gpwjhlkdcf 21 #2 Postado 22 Junho, 2013 É 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 #3 Postado 23 Junho, 2013 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 #4 Postado 23 Junho, 2013 @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 #5 Postado 24 Junho, 2013 (editado) XXXXX Editado 5 Outubro, 2016 por Conde2 Compartilhar este post Link para o post Compartilhar em outros sites
Eventide 7 #6 Postado 25 Junho, 2013 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 #7 Postado 25 Junho, 2013 (editado) XXXXX Editado 5 Outubro, 2016 por Conde2 Compartilhar este post Link para o post Compartilhar em outros sites
Gpwjhlkdcf 21 #8 Postado 26 Junho, 2013 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 #9 Postado 27 Junho, 2013 (editado) XXXXX Editado 5 Outubro, 2016 por Conde2 Compartilhar este post Link para o post Compartilhar em outros sites
Eventide 7 #10 Postado 27 Junho, 2013 (editado) 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 27 Junho, 2013 por Eventide Compartilhar este post Link para o post Compartilhar em outros sites
Gpwjhlkdcf 21 #11 Postado 27 Junho, 2013 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 #12 Postado 28 Junho, 2013 (editado) XXXXX Editado 5 Outubro, 2016 por Conde2 Compartilhar este post Link para o post Compartilhar em outros sites