split up calculate shadows a bit so it is a bit more managable

This commit is contained in:
Tim Anema 2014-09-27 15:58:15 -04:00
parent 9dd4e53119
commit 735d565142
2 changed files with 135 additions and 83 deletions

View File

@ -168,6 +168,7 @@ function body:refresh()
self.data[8] = self.y - self.oy + self.height self.data[8] = self.y - self.oy + self.height
end end
end end
-- set position -- set position
function body:setPosition(x, y) function body:setPosition(x, y)
if x ~= self.x or y ~= self.y then if x ~= self.x or y ~= self.y then
@ -177,6 +178,7 @@ function body:setPosition(x, y)
self.world.changed = true self.world.changed = true
end end
end end
-- set x position -- set x position
function body:setX(x) function body:setX(x)
if x ~= self.x then if x ~= self.x then
@ -185,6 +187,7 @@ function body:setX(x)
self.world.changed = true self.world.changed = true
end end
end end
-- set y position -- set y position
function body:setY(y) function body:setY(y)
if y ~= self.y then if y ~= self.y then
@ -193,30 +196,37 @@ function body:setY(y)
self.world.changed = true self.world.changed = true
end end
end end
-- get x position -- get x position
function body:getX() function body:getX()
return self.x return self.x
end end
-- get y position -- get y position
function body:getY(y) function body:getY(y)
return self.y return self.y
end end
-- get width -- get width
function body:getWidth() function body:getWidth()
return self.width return self.width
end end
-- get height -- get height
function body:getHeight() function body:getHeight()
return self.height return self.height
end end
-- get image width -- get image width
function body:getImageWidth() function body:getImageWidth()
return self.imgWidth return self.imgWidth
end end
-- get image height -- get image height
function body:getImageHeight() function body:getImageHeight()
return self.imgHeight return self.imgHeight
end end
-- set dimension -- set dimension
function body:setDimension(width, height) function body:setDimension(width, height)
self.width = width self.width = width
@ -224,6 +234,7 @@ function body:setDimension(width, height)
self:refresh() self:refresh()
self.world.changed = true self.world.changed = true
end end
-- set offset -- set offset
function body:setOffset(ox, oy) function body:setOffset(ox, oy)
if ox ~= self.ox or oy ~= self.oy then if ox ~= self.ox or oy ~= self.oy then
@ -235,6 +246,7 @@ function body:setOffset(ox, oy)
self.world.changed = true self.world.changed = true
end end
end end
-- set offset -- set offset
function body:setImageOffset(ix, iy) function body:setImageOffset(ix, iy)
if ix ~= self.ix or iy ~= self.iy then if ix ~= self.ix or iy ~= self.iy then
@ -244,6 +256,7 @@ function body:setImageOffset(ix, iy)
self.world.changed = true self.world.changed = true
end end
end end
-- set offset -- set offset
function body:setNormalOffset(nx, ny) function body:setNormalOffset(nx, ny)
if nx ~= self.nx or ny ~= self.ny then if nx ~= self.nx or ny ~= self.ny then
@ -253,6 +266,7 @@ function body:setNormalOffset(nx, ny)
self.world.changed = true self.world.changed = true
end end
end end
-- set glow color -- set glow color
function body:setGlowColor(red, green, blue) function body:setGlowColor(red, green, blue)
self.glowRed = red self.glowRed = red
@ -260,15 +274,18 @@ function body:setGlowColor(red, green, blue)
self.glowBlue = blue self.glowBlue = blue
self.world.changed = true self.world.changed = true
end end
-- set glow alpha -- set glow alpha
function body:setGlowStrength(strength) function body:setGlowStrength(strength)
self.glowStrength = strength self.glowStrength = strength
self.world.changed = true self.world.changed = true
end end
-- get radius -- get radius
function body:getRadius() function body:getRadius()
return self.radius return self.radius
end end
-- set radius -- set radius
function body:setRadius(radius) function body:setRadius(radius)
if radius ~= self.radius then if radius ~= self.radius then
@ -276,25 +293,30 @@ function body:setRadius(radius)
self.world.changed = true self.world.changed = true
end end
end end
-- set polygon data -- set polygon data
function body:setPoints(...) function body:setPoints(...)
self.data = {...} self.data = {...}
self.world.changed = true self.world.changed = true
end end
-- get polygon data -- get polygon data
function body:getPoints() function body:getPoints()
return unpack(self.data) return unpack(self.data)
end end
-- set shadow on/off -- set shadow on/off
function body:setShadow(b) function body:setShadow(b)
self.castsNoShadow = not b self.castsNoShadow = not b
self.world.changed = true self.world.changed = true
end end
-- set shine on/off -- set shine on/off
function body:setShine(b) function body:setShine(b)
self.shine = b self.shine = b
self.world.changed = true self.world.changed = true
end end
-- set glass color -- set glass color
function body:setColor(red, green, blue) function body:setColor(red, green, blue)
self.red = red self.red = red
@ -302,27 +324,33 @@ function body:setColor(red, green, blue)
self.blue = blue self.blue = blue
self.world.changed = true self.world.changed = true
end end
-- set glass alpha -- set glass alpha
function body:setAlpha(alpha) function body:setAlpha(alpha)
self.alpha = alpha self.alpha = alpha
self.world.changed = true self.world.changed = true
end end
-- set reflection on/off -- set reflection on/off
function body:setReflection(reflection) function body:setReflection(reflection)
self.reflection = reflection self.reflection = reflection
end end
-- set refraction on/off -- set refraction on/off
function body:setRefraction(refraction) function body:setRefraction(refraction)
self.refraction = refraction self.refraction = refraction
end end
-- set reflective on other objects on/off -- set reflective on other objects on/off
function body:setReflective(reflective) function body:setReflective(reflective)
self.reflective = reflective self.reflective = reflective
end end
-- set refractive on other objects on/off -- set refractive on other objects on/off
function body:setRefractive(refractive) function body:setRefractive(refractive)
self.refractive = refractive self.refractive = refractive
end end
-- set image -- set image
function body:setImage(img) function body:setImage(img)
if img then if img then
@ -333,6 +361,7 @@ function body:setImage(img)
self.iy = self.imgHeight * 0.5 self.iy = self.imgHeight * 0.5
end end
end end
-- set normal -- set normal
function body:setNormalMap(normal, width, height, nx, ny) function body:setNormalMap(normal, width, height, nx, ny)
if normal then if normal then
@ -355,10 +384,12 @@ function body:setNormalMap(normal, width, height, nx, ny)
self.normalMesh = nil self.normalMesh = nil
end end
end end
-- set height map -- set height map
function body:setHeightMap(heightMap, strength) function body:setHeightMap(heightMap, strength)
self:setNormalMap(height_map_conv.toNormalMap(heightMap, strength)) self:setNormalMap(height_map_conv.toNormalMap(heightMap, strength))
end end
-- generate flat normal map -- generate flat normal map
function body:generateNormalMapFlat(mode) function body:generateNormalMapFlat(mode)
local imgData = self.img:getData() local imgData = self.img:getData()
@ -388,6 +419,7 @@ function body:generateNormalMapFlat(mode)
self:setNormalMap(love.graphics.newImage(imgNormalData)) self:setNormalMap(love.graphics.newImage(imgNormalData))
end end
-- generate faded normal map -- generate faded normal map
function body:generateNormalMapGradient(horizontalGradient, verticalGradient) function body:generateNormalMapGradient(horizontalGradient, verticalGradient)
local imgData = self.img:getData() local imgData = self.img:getData()
@ -428,6 +460,7 @@ function body:generateNormalMapGradient(horizontalGradient, verticalGradient)
self:setNormalMap(love.graphics.newImage(imgNormalData)) self:setNormalMap(love.graphics.newImage(imgNormalData))
end end
-- generate normal map -- generate normal map
function body:generateNormalMap(strength) function body:generateNormalMap(strength)
self:setNormalMap(height_map_conv.toNormalMap(self.img, strength)) self:setNormalMap(height_map_conv.toNormalMap(self.img, strength))

View File

@ -119,7 +119,6 @@ function light:updateShadow()
and self.y + self.range > self.world.translate_y and self.y - self.range < love.graphics.getHeight() + self.world.translate_y and self.y + self.range > self.world.translate_y and self.y - self.range < love.graphics.getHeight() + self.world.translate_y
then then
local lightposrange = {self.x, love.graphics.getHeight() - self.y, self.range} local lightposrange = {self.x, love.graphics.getHeight() - self.y, self.range}
local light = self
self.world.direction = self.world.direction + 0.002 self.world.direction = self.world.direction + 0.002
self.world.shader:send("lightPosition", {self.x - self.world.translate_x, love.graphics.getHeight() - (self.y - self.world.translate_y), self.z}) self.world.shader:send("lightPosition", {self.x - self.world.translate_x, love.graphics.getHeight() - (self.y - self.world.translate_y), self.z})
self.world.shader:send("lightRange", self.range) self.world.shader:send("lightRange", self.range)
@ -133,7 +132,7 @@ function light:updateShadow()
love.graphics.clear() love.graphics.clear()
-- calculate shadows -- calculate shadows
local shadow_geometry = self.calculateShadows(light, self.world.body) local shadow_geometry = self:calculateShadows()
-- draw shadow -- draw shadow
love.graphics.setInvertedStencil(stencils.shadow(shadow_geometry, self.world.body)) love.graphics.setInvertedStencil(stencils.shadow(shadow_geometry, self.world.body))
@ -187,24 +186,42 @@ function light:drawShine()
end end
end end
function light.calculateShadows(light, body) local shadowLength = 100000
function light:calculateShadows()
local shadowGeometry = {} local shadowGeometry = {}
local shadowLength = 100000 local body = self.world.body
for i = 1, #body do for i = 1, #body do
local current
if body[i].shadowType == "rectangle" or body[i].shadowType == "polygon" then if body[i].shadowType == "rectangle" or body[i].shadowType == "polygon" then
curPolygon = body[i].data current = self:calculatePolyShadow(body[i])
if not body[i].castsNoShadow then elseif body[i].shadowType == "circle" then
current = self:calculateCircleShadow(body[i])
end
if current ~= nil then
shadowGeometry[#shadowGeometry + 1] = current
end
end
return shadowGeometry
end
function light:calculatePolyShadow(poly)
if poly.castsNoShadow then
return nil
end
local curPolygon = poly.data
local edgeFacingTo = {} local edgeFacingTo = {}
for k = 1, #curPolygon, 2 do for k = 1, #curPolygon, 2 do
local indexOfNextVertex = (k + 2) % #curPolygon local indexOfNextVertex = (k + 2) % #curPolygon
local normal = {-curPolygon[indexOfNextVertex+1] + curPolygon[k + 1], curPolygon[indexOfNextVertex] - curPolygon[k]} local normal = {-curPolygon[indexOfNextVertex+1] + curPolygon[k + 1], curPolygon[indexOfNextVertex] - curPolygon[k]}
local lightToPoint = {curPolygon[k] - light.x, curPolygon[k + 1] - light.y} local selfToPoint = {curPolygon[k] - self.x, curPolygon[k + 1] - self.y}
normal = vector.normalize(normal) normal = vector.normalize(normal)
lightToPoint = vector.normalize(lightToPoint) selfToPoint = vector.normalize(selfToPoint)
local dotProduct = vector.dot(normal, lightToPoint) local dotProduct = vector.dot(normal, selfToPoint)
if dotProduct > 0 then table.insert(edgeFacingTo, true) if dotProduct > 0 then table.insert(edgeFacingTo, true)
else table.insert(edgeFacingTo, false) end else table.insert(edgeFacingTo, false) end
end end
@ -217,17 +234,17 @@ function light.calculateShadows(light, body)
curShadowGeometry[1] = curPolygon[nextIndex*2-1] curShadowGeometry[1] = curPolygon[nextIndex*2-1]
curShadowGeometry[2] = curPolygon[nextIndex*2] curShadowGeometry[2] = curPolygon[nextIndex*2]
local lightVecFrontBack = vector.normalize({curPolygon[nextIndex*2-1] - light.x, curPolygon[nextIndex*2] - light.y}) local selfVecFrontBack = vector.normalize({curPolygon[nextIndex*2-1] - self.x, curPolygon[nextIndex*2] - self.y})
curShadowGeometry[3] = curShadowGeometry[1] + lightVecFrontBack[1] * shadowLength curShadowGeometry[3] = curShadowGeometry[1] + selfVecFrontBack[1] * shadowLength
curShadowGeometry[4] = curShadowGeometry[2] + lightVecFrontBack[2] * shadowLength curShadowGeometry[4] = curShadowGeometry[2] + selfVecFrontBack[2] * shadowLength
elseif not edgeFacingTo[k] and edgeFacingTo[nextIndex] then elseif not edgeFacingTo[k] and edgeFacingTo[nextIndex] then
curShadowGeometry[7] = curPolygon[nextIndex*2-1] curShadowGeometry[7] = curPolygon[nextIndex*2-1]
curShadowGeometry[8] = curPolygon[nextIndex*2] curShadowGeometry[8] = curPolygon[nextIndex*2]
local lightVecBackFront = vector.normalize({curPolygon[nextIndex*2-1] - light.x, curPolygon[nextIndex*2] - light.y}) local selfVecBackFront = vector.normalize({curPolygon[nextIndex*2-1] - self.x, curPolygon[nextIndex*2] - self.y})
curShadowGeometry[5] = curShadowGeometry[7] + lightVecBackFront[1] * shadowLength curShadowGeometry[5] = curShadowGeometry[7] + selfVecBackFront[1] * shadowLength
curShadowGeometry[6] = curShadowGeometry[8] + lightVecBackFront[2] * shadowLength curShadowGeometry[6] = curShadowGeometry[8] + selfVecBackFront[2] * shadowLength
end end
end end
if curShadowGeometry[1] if curShadowGeometry[1]
@ -239,44 +256,46 @@ function light.calculateShadows(light, body)
and curShadowGeometry[7] and curShadowGeometry[7]
and curShadowGeometry[8] and curShadowGeometry[8]
then then
curShadowGeometry.alpha = body[i].alpha curShadowGeometry.alpha = poly.alpha
curShadowGeometry.red = body[i].red curShadowGeometry.red = poly.red
curShadowGeometry.green = body[i].green curShadowGeometry.green = poly.green
curShadowGeometry.blue = body[i].blue curShadowGeometry.blue = poly.blue
shadowGeometry[#shadowGeometry + 1] = curShadowGeometry return curShadowGeometry
else
return nil
end end
end
function light:calculateCircleShadow(circle)
if circle.castsNoShadow then
return nil
end end
elseif body[i].shadowType == "circle" then local length = math.sqrt(math.pow(self.x - (circle.x - circle.ox), 2) + math.pow(self.y - (circle.y - circle.oy), 2))
if not body[i].castsNoShadow then if length >= circle.radius and length <= self.range then
local length = math.sqrt(math.pow(light.x - (body[i].x - body[i].ox), 2) + math.pow(light.y - (body[i].y - body[i].oy), 2))
if length >= body[i].radius and length <= light.range then
local curShadowGeometry = {} local curShadowGeometry = {}
local angle = math.atan2(light.x - (body[i].x - body[i].ox), (body[i].y - body[i].oy) - light.y) + math.pi / 2 local angle = math.atan2(self.x - (circle.x - circle.ox), (circle.y - circle.oy) - self.y) + math.pi / 2
local x2 = ((body[i].x - body[i].ox) + math.sin(angle) * body[i].radius) local x2 = ((circle.x - circle.ox) + math.sin(angle) * circle.radius)
local y2 = ((body[i].y - body[i].oy) - math.cos(angle) * body[i].radius) local y2 = ((circle.y - circle.oy) - math.cos(angle) * circle.radius)
local x3 = ((body[i].x - body[i].ox) - math.sin(angle) * body[i].radius) local x3 = ((circle.x - circle.ox) - math.sin(angle) * circle.radius)
local y3 = ((body[i].y - body[i].oy) + math.cos(angle) * body[i].radius) local y3 = ((circle.y - circle.oy) + math.cos(angle) * circle.radius)
curShadowGeometry[1] = x2 curShadowGeometry[1] = x2
curShadowGeometry[2] = y2 curShadowGeometry[2] = y2
curShadowGeometry[3] = x3 curShadowGeometry[3] = x3
curShadowGeometry[4] = y3 curShadowGeometry[4] = y3
curShadowGeometry[5] = x3 - (light.x - x3) * shadowLength curShadowGeometry[5] = x3 - (self.x - x3) * shadowLength
curShadowGeometry[6] = y3 - (light.y - y3) * shadowLength curShadowGeometry[6] = y3 - (self.y - y3) * shadowLength
curShadowGeometry[7] = x2 - (light.x - x2) * shadowLength curShadowGeometry[7] = x2 - (self.x - x2) * shadowLength
curShadowGeometry[8] = y2 - (light.y - y2) * shadowLength curShadowGeometry[8] = y2 - (self.y - y2) * shadowLength
curShadowGeometry.alpha = body[i].alpha curShadowGeometry.alpha = circle.alpha
curShadowGeometry.red = body[i].red curShadowGeometry.red = circle.red
curShadowGeometry.green = body[i].green curShadowGeometry.green = circle.green
curShadowGeometry.blue = body[i].blue curShadowGeometry.blue = circle.blue
shadowGeometry[#shadowGeometry + 1] = curShadowGeometry return curShadowGeometry
else
return nil
end end
end
end
end
return shadowGeometry
end end
function light:drawPixelShadow() function light:drawPixelShadow()