Advertisement
SkyTheCoder

3D Explosion Simulator

Jun 8th, 2014
400
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 15.97 KB | None | 0 0
  1.  
  2. --# ExampleA
  3. ExampleA = class()
  4.  
  5. function ExampleA:init()
  6. self:start()
  7. end
  8.  
  9. function ExampleA:start()
  10. self.rot = false
  11. if self.t ~= nil then
  12. tween.stop(self.t)
  13. end
  14. self.t = tween.delay(3, function()
  15. self.rot = true
  16. end)
  17. self.cam = vec2(0, -2)
  18. self.explosions = {Explosion(vec3(0, 0, 0), true)}
  19. parameter.action("New Explosion", function()
  20. table.insert(self.explosions, Explosion(vec3(math.random(-5, 5), 0, math.random(-5, 5))))
  21. end)
  22.  
  23. parameter.boolean("Anarchy", false)
  24. end
  25.  
  26. function ExampleA:draw()
  27. if self.rot then
  28. self.cam = self.cam:rotate(math.rad(45 / 60))
  29. end
  30.  
  31. if Anarchy and ElapsedTime % 1 <= 5 / 60 then
  32. table.insert(self.explosions, Explosion(vec3(math.random(-5, 5), 0, math.random(-5, 5))))
  33. end
  34.  
  35. camera(self.cam.x, 0.5, self.cam.y, 0, 0.5, 0)
  36. perspective(45)
  37.  
  38. for k, v in pairs(self.explosions) do
  39. v:draw()
  40.  
  41. if v.stopped then
  42. table.remove(self.explosions, k)
  43. end
  44. end
  45.  
  46. rotate(90, 1, 0, 0)
  47.  
  48. scale(0.01)
  49.  
  50. sprite("Platformer Art:Block Brick")
  51. end
  52.  
  53. function ExampleA:touched(touch)
  54. tween.stop(self.t)
  55. self.rot = false
  56. self.cam = self.cam:rotate(math.rad(touch.deltaX))
  57. self.t = tween.delay(3, function()
  58. self.rot = true
  59. end)
  60. end
  61.  
  62. --# ExampleB
  63. ExampleB = class()
  64.  
  65. function ExampleB:init()
  66. self:start()
  67. end
  68.  
  69. function ExampleB:start()
  70. self.exp = nil
  71.  
  72. -- all the unique vertices that make up a cube
  73. local vertices = {
  74. vec3(-0.5, -0.5, 0.5), -- Left bottom front
  75. vec3( 0.5, -0.5, 0.5), -- Right bottom front
  76. vec3( 0.5, 0.5, 0.5), -- Right top front
  77. vec3(-0.5, 0.5, 0.5), -- Left top front
  78. vec3(-0.5, -0.5, -0.5), -- Left bottom back
  79. vec3( 0.5, -0.5, -0.5), -- Right bottom back
  80. vec3( 0.5, 0.5, -0.5), -- Right top back
  81. vec3(-0.5, 0.5, -0.5), -- Left top back
  82. }
  83.  
  84.  
  85. -- now construct a cube out of the vertices above
  86. local cubeverts = {
  87. -- Front
  88. vertices[1], vertices[2], vertices[3],
  89. vertices[1], vertices[3], vertices[4],
  90. -- Right
  91. vertices[2], vertices[6], vertices[7],
  92. vertices[2], vertices[7], vertices[3],
  93. -- Back
  94. vertices[6], vertices[5], vertices[8],
  95. vertices[6], vertices[8], vertices[7],
  96. -- Left
  97. vertices[5], vertices[1], vertices[4],
  98. vertices[5], vertices[4], vertices[8],
  99. -- Top
  100. vertices[4], vertices[3], vertices[7],
  101. vertices[4], vertices[7], vertices[8],
  102. -- Bottom
  103. vertices[5], vertices[6], vertices[2],
  104. vertices[5], vertices[2], vertices[1],
  105. }
  106.  
  107. -- all the unique texture positions needed
  108. local texvertices = { vec2(0.03,0.24),
  109. vec2(0.97,0.24),
  110. vec2(0.03,0.69),
  111. vec2(0.97,0.69) }
  112.  
  113. -- apply the texture coordinates to each triangle
  114. local cubetexCoords = {
  115. -- Front
  116. texvertices[1], texvertices[2], texvertices[4],
  117. texvertices[1], texvertices[4], texvertices[3],
  118. -- Right
  119. texvertices[1], texvertices[2], texvertices[4],
  120. texvertices[1], texvertices[4], texvertices[3],
  121. -- Back
  122. texvertices[1], texvertices[2], texvertices[4],
  123. texvertices[1], texvertices[4], texvertices[3],
  124. -- Left
  125. texvertices[1], texvertices[2], texvertices[4],
  126. texvertices[1], texvertices[4], texvertices[3],
  127. -- Top
  128. texvertices[1], texvertices[2], texvertices[4],
  129. texvertices[1], texvertices[4], texvertices[3],
  130. -- Bottom
  131. texvertices[1], texvertices[2], texvertices[4],
  132. texvertices[1], texvertices[4], texvertices[3],
  133. }
  134.  
  135. -- now we make our 3 different block types
  136. self.ms = mesh()
  137. self.ms.vertices = cubeverts
  138. self.ms.texture = "Planet Cute:Stone Block"
  139. self.ms.texCoords = cubetexCoords
  140. self.ms:setColors(255,255,255,255)
  141.  
  142. self.md = mesh()
  143. self.md.vertices = cubeverts
  144. self.md.texture = "Planet Cute:Dirt Block"
  145. self.md.texCoords = cubetexCoords
  146. self.md:setColors(255,255,255,255)
  147.  
  148. self.mg = mesh()
  149. self.mg.vertices = cubeverts
  150. self.mg.texture = "Planet Cute:Grass Block"
  151. self.mg.texCoords = cubetexCoords
  152. self.mg:setColors(255,255,255,255)
  153.  
  154. -- currently doesnt work properly without backfaces
  155. self.mw = mesh()
  156. self.mw.vertices = cubeverts
  157. self.mw.texture = "Planet Cute:Water Block"
  158. self.mw.texCoords = cubetexCoords
  159. self.mw:setColors(255,255,255,100)
  160.  
  161. -- stick 'em in a table
  162. self.blocks = { self.mg, self.md, self.ms }
  163.  
  164. -- our scene itself
  165. -- numbers correspond to block positions in the blockTypes table
  166. -- bottom middle top
  167. self.scene = { { {1, 1, 1, 1, 1, 1}, {1, 1, 1, 1, 0, 0}, {0, 0, 0, 0, 0, 0}, },
  168. { {1, 1, 1, 1, 1, 1}, {1, 1, 1, 0, 0, 0}, {0, 0, 0, 0, 0, 0}, },
  169. { {1, 1, 1, 1, 1, 1}, {1, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0}, },
  170. { {1, 1, 1, 1, 1, 1}, {1, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0}, },
  171. { {1, 1, 1, 1, 1, 1}, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0}, },
  172. { {1, 1, 1, 1, 1, 1}, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0}, },
  173. }
  174.  
  175. self.time = 0
  176. end
  177.  
  178. function ExampleB:draw()
  179. self.time = self.time + DeltaTime
  180.  
  181. pushMatrix()
  182. pushStyle()
  183.  
  184. -- Make a floor
  185. --translate(0,-Size/2,0)
  186. --rotate(Angle,0,1,0)
  187.  
  188. local norm = vec3(0.1, 1, 0):normalize()
  189.  
  190. camera(0, 0.23, -0.12, 0, 0.15, 2, norm.x, norm.y, norm.z)
  191. perspective(45)
  192.  
  193. rotate(90,1,0,0)
  194. --sprite("SpaceCute:Background", 0, 0, 300, 300)
  195.  
  196. -- render each block in turn
  197. for zi,zv in ipairs(self.scene) do
  198. for yi,yv in ipairs(zv) do
  199. for xi, xv in ipairs(yv) do
  200. -- apply each transform need - rotate, scale, translate to the correct place
  201. resetMatrix()
  202. --rotate(Angle,0,1,0)
  203.  
  204. --local s = Size*0.25
  205. --scale(s,s,s)
  206.  
  207. scale(0.25)
  208.  
  209. translate(xi-2, yi-2, zi-2) -- renders based on corner
  210. -- so -2 fudges it near center
  211.  
  212. if xv > 0 then
  213. self.blocks[xv]:draw()
  214. end
  215. end
  216. end
  217. end
  218.  
  219. popStyle()
  220. popMatrix()
  221.  
  222. if self.exp ~= nil then
  223. self.exp:draw()
  224. if self.exp.stopped then
  225. self.exp = nil
  226. self.time = 0
  227. end
  228. elseif self.time >= 3 then
  229. self.exp = Explosion(vec3(0, 0, 0.5))
  230. end
  231. end
  232.  
  233. function ExampleB:touched(touch)
  234.  
  235. end
  236.  
  237. --# Explosion
  238. Explosion
  239.  
  240. = class() -- I usually move the "= class()" to another line so if it crashes, all you see is "Explosion"
  241.  
  242. local expScene = {}
  243. local expSim = {}
  244. local fireSim = {}
  245. local fireTrail = {}
  246.  
  247. local rad, sin, cos = math.rad, math.sin, math.cos -- efficiency
  248.  
  249. for i = 0, 360 do -- Generate mushroom particles
  250. local a = i % 90 * 4 -- Angle of particle
  251. local d = i / 360 -- Distance from center
  252. local r = rad(a) -- Radian version of angle
  253. local s, c = sin(r), cos(r) -- Sine and cosine of angle
  254. table.insert(expSim, {x = s * d, y = 0, z = c * d, m = 3, a = 0, s = 1}) -- Create particle
  255. end
  256.  
  257. for i = 0, 360, 22.5 do -- Generate fire burst particles
  258. local a = i % 90 * 4 -- Angle of particle
  259. local d = i / 720 + 0.5 -- Distance from center
  260. local r = rad(a) -- Radian version of angle
  261. local s, c = sin(r), cos(r) -- Sine and cosine of angle
  262. table.insert(fireSim, {x = s * d, y = 0, z = c * d, m = d * 3, a = 0, s = 1.2}) -- Create particle
  263. end
  264.  
  265. pushStyle()
  266.  
  267. noStroke()
  268.  
  269. for f = 0, 180 do -- Pre-simulate particle physics and pre-render particles for unlimited explosions with no lag
  270. if f <= 120 then
  271. for a = 1, 10 do -- Generate stem particles
  272. table.insert(expSim, {x = sin(f + a * 0.5), y = 0, z = cos(f + a * 0.5), m = 3, a = 0, s = 1}) -- Create particle
  273. end
  274. else
  275. local c = 0 -- Disintegrate particles after prime
  276. for i = 1, #expSim do
  277. table.remove(expSim, i)
  278. c = c + 1
  279. if c > 32 then -- Limit maximum removals per frame (disintegrate effect)
  280. break
  281. end
  282. end
  283. end
  284.  
  285. for k, v in pairs(expSim) do -- Remove edge particles
  286. if expSim[k].x <= -10 or expSim[k].x >= 10 then -- Check if on screen edge
  287. table.remove(expSim, k)
  288. end
  289. end
  290.  
  291. for k, v in pairs(fireSim) do -- Remove edge particles
  292. if fireSim[k].y <= -5 then -- Check if on screen edge
  293. table.remove(fireSim, k)
  294. end
  295. end
  296.  
  297. local c = 0
  298.  
  299. for k, v in pairs(expSim) do -- Disintegrate old particles
  300. expSim[k].a = expSim[k].a + 1 -- Add age
  301. if expSim[k].a >= 80 then
  302. table.remove(expSim, k)
  303. c = c + 1
  304. if c > 15 then -- Limit maximum removals per frame (disintegrate effect)
  305. break
  306. end
  307. end
  308. end
  309.  
  310. expScene[f] = image(128, 128) -- Init image for current frame
  311. setContext(expScene[f]) -- Pre-render all the particles
  312.  
  313. for k, v in pairs(fireTrail) do -- Draw smoke trail behind fire
  314. fireTrail[k].a = fireTrail[k].a + 1
  315. fill(127)
  316. ellipse(v.x * 5 + 64, v.y, 5)
  317.  
  318. if fireTrail[k].a >= 10 then
  319. table.remove(fireTrail, k)
  320. end
  321. end
  322.  
  323. for i = 1, #fireSim do -- Draw fire particles
  324. fireSim[i].s = fireSim[i].s * 0.993 -- Particle physics
  325. fireSim[i].x = fireSim[i].x * math.max(1, fireSim[i].s)
  326. fireSim[i].z = fireSim[i].z * math.max(1, fireSim[i].s)
  327. fireSim[i].m = fireSim[i].m - 0.15
  328. fireSim[i].y = fireSim[i].y + fireSim[i].m
  329.  
  330. local tbl = {}
  331. for k, v in pairs(fireSim[i]) do
  332. tbl[k] = v
  333. end
  334. table.insert(fireTrail, tbl)
  335. fireTrail[#fireTrail].a = 0
  336.  
  337. pushStyle()
  338.  
  339. local middle = color(255, 255, 255, 255)
  340. local inner = color(255, 127, 0, 255)
  341. local rim = color(255, 0, 0, 255)--]]
  342.  
  343. local a = math.abs(fireSim[i].x * 5) / 16
  344. local b = math.abs(fireSim[i].x * 5) / 32
  345. fill(rim:mix(inner:mix(middle, a), b))
  346. ellipse(fireSim[i].x * 5 + 64, fireSim[i].y, 5)
  347.  
  348. popStyle()
  349. end
  350.  
  351. for i = 1, #expSim do -- Draw the explosion particles
  352. if expSim[i].y < 50 then -- Particle physics
  353. expSim[i].x = expSim[i].x * (1.05 * expSim[i].s)
  354. expSim[i].z = expSim[i].z * (1.05 * expSim[i].s)
  355. else
  356. expSim[i].x = expSim[i].x * (0.99 * expSim[i].s)
  357. expSim[i].z = expSim[i].z * (0.99 * expSim[i].s)
  358. end
  359. expSim[i].m = expSim[i].m * 0.95
  360. expSim[i].y = expSim[i].y + expSim[i].m
  361. if expSim[i].y >= 50 then
  362. expSim[i].y = expSim[i].y + 0.1
  363. end
  364.  
  365. pushStyle()
  366.  
  367. -- Old colors, just saved for archiving
  368.  
  369. --[[local middle = color(255, 255, 255, 255)
  370. local inner = color(255, 127, 0, 255)
  371. local rim = color(255, 0, 0, 255)--]]
  372.  
  373. -- New colors
  374.  
  375. local middle = color(191)
  376. local inner = color(127)
  377. local rim = color(63)
  378.  
  379. local a = math.abs(expSim[i].x * 5) / 16 -- Color calculation
  380. local b = math.abs(expSim[i].x * 5) / 32
  381. fill(rim:mix(inner:mix(middle, a), b))
  382.  
  383. ellipse(expSim[i].x * 5 + 64, expSim[i].y, 5)
  384. popStyle()
  385. end
  386. setContext()
  387. end
  388.  
  389. popStyle()
  390.  
  391. ----
  392. -- pos: vec3 (optional, vec3(x, y, z))
  393. -- loop: boolean (optional, true or false)
  394. -- speed: number (optional, 0.5 - 2 etc.)
  395. -- res: number (optional, 0.5 - 2 etc.)
  396. ----
  397.  
  398. function Explosion:init(pos, loop, speed, res)
  399. self.pos = pos or vec3(0, 0, 0)
  400. self.loop = loop or false
  401. self.speed = speed or 1
  402. self.res = res or 1
  403. self.time = 0
  404. self.stopped = false
  405. self.m = mesh() -- Basic 3D plane mesh
  406. self.m.vertices = {
  407. vec3(-0.5, 0, 0), vec3(-0.5, 1, 0), vec3(0.5, 1, 0),
  408. vec3(-0.5, 0, 0), vec3(0.5, 1, 0), vec3(0.5, 0, 0),
  409. }
  410. self.m.texCoords = {
  411. vec2(0, 0), vec2(0, 1), vec2(1, 1),
  412. vec2(0, 0), vec2(1, 1), vec2(1, 0),
  413. }
  414. self.m:setColors(color(255))
  415. self.m.shader = shader(Shaders.Discard.vS, Shaders.Discard.fS) -- Simple shader to discard backfaces and non-visible pixels
  416. end
  417.  
  418. function Explosion:draw()
  419. self.time = self.time + DeltaTime * self.speed -- Increment explosion time
  420.  
  421. if self.loop or self.time <= #expScene / 60 then -- If not done
  422. pushMatrix()
  423. pushStyle()
  424.  
  425. translate(self.pos.x, self.pos.y, self.pos.z)
  426.  
  427. smooth()
  428. self.m.texture = expScene[math.floor(self.time % (#expScene / 60) * 60)] -- Assign current pre-rendered frame to mesh
  429. for i = 0, 360, 45 / self.res do -- Resoltion for loop
  430. pushMatrix()
  431. rotate(i, 0, 1, 0)
  432. self.m:draw() -- Draw the mesh
  433. popMatrix()
  434. end
  435. popStyle()
  436. popMatrix()
  437. else
  438. self.stopped = true
  439. end
  440. end
  441.  
  442. --# FPS
  443. FPS = 0
  444. local frames = 0
  445. local time = 0
  446. tween.delay(0, function()
  447. local d = draw
  448. draw = function()
  449. frames = frames + 1
  450. if math.floor(ElapsedTime) ~= math.floor(time) then
  451. FPS = frames - 1
  452. frames = 1
  453. end
  454. time = ElapsedTime
  455. d()
  456. end
  457. end)
  458. --# Main
  459. -- 3D Explosion Simulator
  460.  
  461. spriteBatching(false)
  462.  
  463. -- Use this function to perform your initial setup
  464. function setup()
  465. print("Hello World!")
  466. scenes = {ExampleA(), ExampleB()}
  467. parameter.integer("Scene", 1, #scenes, 1, function()
  468. scenes[Scene]:start()
  469. end)
  470. parameter.watch("FPS")
  471. end
  472.  
  473. -- This function gets called once every frame
  474. function draw()
  475. -- This sets a dark background color
  476. background(40, 40, 50)
  477.  
  478. -- This sets the line thickness
  479. strokeWidth(5)
  480.  
  481. -- Do your drawing here
  482. scenes[Scene]:draw()
  483. end
  484.  
  485. function touched(touch)
  486. scenes[Scene]:touched(touch)
  487. end
  488.  
  489.  
  490. --# Shaders
  491. Shaders = {
  492. Discard = {
  493. vS = [[
  494. //
  495. // A basic vertex shader
  496. //
  497.  
  498. //This is the current model * view * projection matrix
  499. // Codea sets it automatically
  500. uniform mat4 modelViewProjection;
  501.  
  502. //This is the current mesh vertex position, color and tex coord
  503. // Set automatically
  504. attribute vec4 position;
  505. attribute vec4 color;
  506. attribute vec2 texCoord;
  507.  
  508. //This is an output variable that will be passed to the fragment shader
  509. varying lowp vec4 vColor;
  510. varying highp vec2 vTexCoord;
  511.  
  512. void main()
  513. {
  514. //Pass the mesh color to the fragment shader
  515. vColor = color;
  516. vTexCoord = texCoord;
  517.  
  518. //Multiply the vertex position by our combined transform
  519. gl_Position = modelViewProjection * position;
  520. }
  521.  
  522. ]],
  523. fS = [[
  524. //
  525. // A basic fragment shader
  526. //
  527.  
  528. //Default precision qualifier
  529. precision highp float;
  530.  
  531. //This represents the current texture on the mesh
  532. uniform lowp sampler2D texture;
  533.  
  534. //The interpolated vertex color for this fragment
  535. varying lowp vec4 vColor;
  536.  
  537. //The interpolated texture coordinate for this fragment
  538. varying highp vec2 vTexCoord;
  539.  
  540. void main()
  541. {
  542. if (!gl_FrontFacing) discard; // Discard backfaces
  543.  
  544. //Sample the texture at the interpolated coordinate
  545. lowp vec4 col = texture2D( texture, vTexCoord ) * vColor;
  546.  
  547. if (col.a <= 0.8) discard; // Discard non-visible pixels
  548.  
  549. //Set the output color to the texture color
  550. gl_FragColor = col;
  551. }
  552.  
  553. ]],
  554. }
  555. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement