

SpriteEmitterExample = {}

SpriteEmitterExample.poolSize = 64
SpriteEmitterExample.gravity = 0.5
SpriteEmitterExample.sizeMin = 0.05
SpriteEmitterExample.sizeMax = 1.0
SpriteEmitterExample.emissionRate = 0.03
SpriteEmitterExample.impulseMin = vec3(-1.5, 1.0, -1.5)
SpriteEmitterExample.impulseMax = vec3(1.5, 3.0, 1.5)

function SpriteEmitterExample.start()
	SpriteEmitterExample.particles = {}

	for i = 1, SpriteEmitterExample.poolSize do
		local p = {}
		p.sprite = allocSprite()
		p.data = {}
		p.data.textureId = 1
		p.data.texturePos = vec2(65.0, 65.0)
		p.data.textureSize = vec2(16.0, 16.0)
		p.data.position = vec3(0.0, 0.0, 0.0)
		p.data.size = vec2(0.15, 0.15)
		p.data.color = vec4(255.0, 255.0, 255.0, 0.0)
		p.data.billboard = 1.0
		p.data.billboardPixelPerfect = 0.0
		p.vel = vec3(0.0, 0.0, 0.0)
		p.life = 0.0
		p.maxLife = 1.0
		SpriteEmitterExample.particles[i] = p
	end

	SpriteEmitterExample.emitTimer = 0.0
	SpriteEmitterExample.fov = degToRad(60.0)
	SpriteEmitterExample.lastTime = getTime()
end

function emit(p)
	p.data.position = vec3(random(-0.3, 0.3), random(-0.1, 0.1), random(-0.3, 0.3))
	p.vel = vec3(
		random(SpriteEmitterExample.impulseMin.x, SpriteEmitterExample.impulseMax.x),
		random(SpriteEmitterExample.impulseMin.y, SpriteEmitterExample.impulseMax.y),
		random(SpriteEmitterExample.impulseMin.z, SpriteEmitterExample.impulseMax.z))
	p.maxLife = random(1.0, 2.5)
	p.life = p.maxLife

	local s = random(SpriteEmitterExample.sizeMin, SpriteEmitterExample.sizeMax)
	p.data.size = vec2(s, s)
end

function SpriteEmitterExample.update()
	local currentTime = getTime()
	local dt = currentTime - SpriteEmitterExample.lastTime
	SpriteEmitterExample.lastTime = currentTime

	local cameraPos = vec3(0.0, 2.0, 5.0)
	local lookDir = vec3Normalize(cameraPos - vec3(0.0, 1.0, 0.0))
	local cameraMat = mat4LookAt(cameraPos, lookDir, vec3(0.0, 1.0, 0.0))
	setCamera(cameraMat, SpriteEmitterExample.fov)

	SpriteEmitterExample.emitTimer = SpriteEmitterExample.emitTimer + dt
	while SpriteEmitterExample.emitTimer > SpriteEmitterExample.emissionRate do
		SpriteEmitterExample.emitTimer = SpriteEmitterExample.emitTimer - SpriteEmitterExample.emissionRate

		for i = 1, SpriteEmitterExample.poolSize do
			if SpriteEmitterExample.particles[i].life <= 0.0 then
				emit(SpriteEmitterExample.particles[i])

				break
			end
		end
	end

	local drawList = {}

	for i = 1, SpriteEmitterExample.poolSize do
		local p = SpriteEmitterExample.particles[i]

		if p.life > 0.0 then
			p.life = p.life - dt

			p.vel.y = p.vel.y + SpriteEmitterExample.gravity * dt

			p.data.position.x = p.data.position.x + p.vel.x * dt
			p.data.position.y = p.data.position.y + p.vel.y * dt
			p.data.position.z = p.data.position.z + p.vel.z * dt

			p.data.color.w = 255.0 * (p.life / p.maxLife)

			local dx = p.data.position.x - cameraPos.x
			local dy = p.data.position.y - cameraPos.y
			local dz = p.data.position.z - cameraPos.z
			p.distSq = dx * dx + dy * dy + dz * dz

			setSprite(p.sprite, p.data)

			drawList[#drawList + 1] = p
		end
	end

	table.sort(drawList, function(a, b) return a.distSq > b.distSq end)

	for i = 1, #drawList do
		drawSprite(drawList[i].sprite)
	end
end
