SkyTheCoder

3D Explosion Simulator

Jun 8th, 2014
310
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  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. }
RAW Paste Data

Adblocker detected! Please consider disabling it...

We've detected AdBlock Plus or some other adblocking software preventing Pastebin.com from fully loading.

We don't have any obnoxious sound, or popup ads, we actively block these annoying types of ads!

Please add Pastebin.com to your ad blocker whitelist or disable your adblocking software.

×