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
end
end
-- set position
function body:setPosition(x, y)
if x ~= self.x or y ~= self.y then
@ -177,6 +178,7 @@ function body:setPosition(x, y)
self.world.changed = true
end
end
-- set x position
function body:setX(x)
if x ~= self.x then
@ -185,6 +187,7 @@ function body:setX(x)
self.world.changed = true
end
end
-- set y position
function body:setY(y)
if y ~= self.y then
@ -193,30 +196,37 @@ function body:setY(y)
self.world.changed = true
end
end
-- get x position
function body:getX()
return self.x
end
-- get y position
function body:getY(y)
return self.y
end
-- get width
function body:getWidth()
return self.width
end
-- get height
function body:getHeight()
return self.height
end
-- get image width
function body:getImageWidth()
return self.imgWidth
end
-- get image height
function body:getImageHeight()
return self.imgHeight
end
-- set dimension
function body:setDimension(width, height)
self.width = width
@ -224,6 +234,7 @@ function body:setDimension(width, height)
self:refresh()
self.world.changed = true
end
-- set offset
function body:setOffset(ox, oy)
if ox ~= self.ox or oy ~= self.oy then
@ -235,6 +246,7 @@ function body:setOffset(ox, oy)
self.world.changed = true
end
end
-- set offset
function body:setImageOffset(ix, iy)
if ix ~= self.ix or iy ~= self.iy then
@ -244,6 +256,7 @@ function body:setImageOffset(ix, iy)
self.world.changed = true
end
end
-- set offset
function body:setNormalOffset(nx, ny)
if nx ~= self.nx or ny ~= self.ny then
@ -253,6 +266,7 @@ function body:setNormalOffset(nx, ny)
self.world.changed = true
end
end
-- set glow color
function body:setGlowColor(red, green, blue)
self.glowRed = red
@ -260,15 +274,18 @@ function body:setGlowColor(red, green, blue)
self.glowBlue = blue
self.world.changed = true
end
-- set glow alpha
function body:setGlowStrength(strength)
self.glowStrength = strength
self.world.changed = true
end
-- get radius
function body:getRadius()
return self.radius
end
-- set radius
function body:setRadius(radius)
if radius ~= self.radius then
@ -276,25 +293,30 @@ function body:setRadius(radius)
self.world.changed = true
end
end
-- set polygon data
function body:setPoints(...)
self.data = {...}
self.world.changed = true
end
-- get polygon data
function body:getPoints()
return unpack(self.data)
end
-- set shadow on/off
function body:setShadow(b)
self.castsNoShadow = not b
self.world.changed = true
end
-- set shine on/off
function body:setShine(b)
self.shine = b
self.world.changed = true
end
-- set glass color
function body:setColor(red, green, blue)
self.red = red
@ -302,27 +324,33 @@ function body:setColor(red, green, blue)
self.blue = blue
self.world.changed = true
end
-- set glass alpha
function body:setAlpha(alpha)
self.alpha = alpha
self.world.changed = true
end
-- set reflection on/off
function body:setReflection(reflection)
self.reflection = reflection
end
-- set refraction on/off
function body:setRefraction(refraction)
self.refraction = refraction
end
-- set reflective on other objects on/off
function body:setReflective(reflective)
self.reflective = reflective
end
-- set refractive on other objects on/off
function body:setRefractive(refractive)
self.refractive = refractive
end
-- set image
function body:setImage(img)
if img then
@ -333,6 +361,7 @@ function body:setImage(img)
self.iy = self.imgHeight * 0.5
end
end
-- set normal
function body:setNormalMap(normal, width, height, nx, ny)
if normal then
@ -355,10 +384,12 @@ function body:setNormalMap(normal, width, height, nx, ny)
self.normalMesh = nil
end
end
-- set height map
function body:setHeightMap(heightMap, strength)
self:setNormalMap(height_map_conv.toNormalMap(heightMap, strength))
end
-- generate flat normal map
function body:generateNormalMapFlat(mode)
local imgData = self.img:getData()
@ -388,6 +419,7 @@ function body:generateNormalMapFlat(mode)
self:setNormalMap(love.graphics.newImage(imgNormalData))
end
-- generate faded normal map
function body:generateNormalMapGradient(horizontalGradient, verticalGradient)
local imgData = self.img:getData()
@ -428,6 +460,7 @@ function body:generateNormalMapGradient(horizontalGradient, verticalGradient)
self:setNormalMap(love.graphics.newImage(imgNormalData))
end
-- generate normal map
function body:generateNormalMap(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
then
local lightposrange = {self.x, love.graphics.getHeight() - self.y, self.range}
local light = self
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("lightRange", self.range)
@ -133,7 +132,7 @@ function light:updateShadow()
love.graphics.clear()
-- calculate shadows
local shadow_geometry = self.calculateShadows(light, self.world.body)
local shadow_geometry = self:calculateShadows()
-- draw shadow
love.graphics.setInvertedStencil(stencils.shadow(shadow_geometry, self.world.body))
@ -187,24 +186,42 @@ function light:drawShine()
end
end
function light.calculateShadows(light, body)
local shadowGeometry = {}
local shadowLength = 100000
function light:calculateShadows()
local shadowGeometry = {}
local body = self.world.body
for i = 1, #body do
local current
if body[i].shadowType == "rectangle" or body[i].shadowType == "polygon" then
curPolygon = body[i].data
if not body[i].castsNoShadow then
current = self:calculatePolyShadow(body[i])
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 = {}
for k = 1, #curPolygon, 2 do
local indexOfNextVertex = (k + 2) % #curPolygon
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)
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)
else table.insert(edgeFacingTo, false) end
end
@ -217,17 +234,17 @@ function light.calculateShadows(light, body)
curShadowGeometry[1] = curPolygon[nextIndex*2-1]
curShadowGeometry[2] = curPolygon[nextIndex*2]
local lightVecFrontBack = vector.normalize({curPolygon[nextIndex*2-1] - light.x, curPolygon[nextIndex*2] - light.y})
curShadowGeometry[3] = curShadowGeometry[1] + lightVecFrontBack[1] * shadowLength
curShadowGeometry[4] = curShadowGeometry[2] + lightVecFrontBack[2] * shadowLength
local selfVecFrontBack = vector.normalize({curPolygon[nextIndex*2-1] - self.x, curPolygon[nextIndex*2] - self.y})
curShadowGeometry[3] = curShadowGeometry[1] + selfVecFrontBack[1] * shadowLength
curShadowGeometry[4] = curShadowGeometry[2] + selfVecFrontBack[2] * shadowLength
elseif not edgeFacingTo[k] and edgeFacingTo[nextIndex] then
curShadowGeometry[7] = curPolygon[nextIndex*2-1]
curShadowGeometry[8] = curPolygon[nextIndex*2]
local lightVecBackFront = vector.normalize({curPolygon[nextIndex*2-1] - light.x, curPolygon[nextIndex*2] - light.y})
curShadowGeometry[5] = curShadowGeometry[7] + lightVecBackFront[1] * shadowLength
curShadowGeometry[6] = curShadowGeometry[8] + lightVecBackFront[2] * shadowLength
local selfVecBackFront = vector.normalize({curPolygon[nextIndex*2-1] - self.x, curPolygon[nextIndex*2] - self.y})
curShadowGeometry[5] = curShadowGeometry[7] + selfVecBackFront[1] * shadowLength
curShadowGeometry[6] = curShadowGeometry[8] + selfVecBackFront[2] * shadowLength
end
end
if curShadowGeometry[1]
@ -239,45 +256,47 @@ function light.calculateShadows(light, body)
and curShadowGeometry[7]
and curShadowGeometry[8]
then
curShadowGeometry.alpha = body[i].alpha
curShadowGeometry.red = body[i].red
curShadowGeometry.green = body[i].green
curShadowGeometry.blue = body[i].blue
shadowGeometry[#shadowGeometry + 1] = curShadowGeometry
curShadowGeometry.alpha = poly.alpha
curShadowGeometry.red = poly.red
curShadowGeometry.green = poly.green
curShadowGeometry.blue = poly.blue
return curShadowGeometry
else
return nil
end
end
elseif body[i].shadowType == "circle" then
if not body[i].castsNoShadow 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
function light:calculateCircleShadow(circle)
if circle.castsNoShadow then
return nil
end
local length = math.sqrt(math.pow(self.x - (circle.x - circle.ox), 2) + math.pow(self.y - (circle.y - circle.oy), 2))
if length >= circle.radius and length <= self.range then
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 x2 = ((body[i].x - body[i].ox) + math.sin(angle) * body[i].radius)
local y2 = ((body[i].y - body[i].oy) - math.cos(angle) * body[i].radius)
local x3 = ((body[i].x - body[i].ox) - math.sin(angle) * body[i].radius)
local y3 = ((body[i].y - body[i].oy) + math.cos(angle) * body[i].radius)
local angle = math.atan2(self.x - (circle.x - circle.ox), (circle.y - circle.oy) - self.y) + math.pi / 2
local x2 = ((circle.x - circle.ox) + math.sin(angle) * circle.radius)
local y2 = ((circle.y - circle.oy) - math.cos(angle) * circle.radius)
local x3 = ((circle.x - circle.ox) - math.sin(angle) * circle.radius)
local y3 = ((circle.y - circle.oy) + math.cos(angle) * circle.radius)
curShadowGeometry[1] = x2
curShadowGeometry[2] = y2
curShadowGeometry[3] = x3
curShadowGeometry[4] = y3
curShadowGeometry[5] = x3 - (light.x - x3) * shadowLength
curShadowGeometry[6] = y3 - (light.y - y3) * shadowLength
curShadowGeometry[7] = x2 - (light.x - x2) * shadowLength
curShadowGeometry[8] = y2 - (light.y - y2) * shadowLength
curShadowGeometry.alpha = body[i].alpha
curShadowGeometry.red = body[i].red
curShadowGeometry.green = body[i].green
curShadowGeometry.blue = body[i].blue
shadowGeometry[#shadowGeometry + 1] = curShadowGeometry
curShadowGeometry[5] = x3 - (self.x - x3) * shadowLength
curShadowGeometry[6] = y3 - (self.y - y3) * shadowLength
curShadowGeometry[7] = x2 - (self.x - x2) * shadowLength
curShadowGeometry[8] = y2 - (self.y - y2) * shadowLength
curShadowGeometry.alpha = circle.alpha
curShadowGeometry.red = circle.red
curShadowGeometry.green = circle.green
curShadowGeometry.blue = circle.blue
return curShadowGeometry
else
return nil
end
end
end
end
return shadowGeometry
end
function light:drawPixelShadow()
if self.visible then