mirror of
https://github.com/tanema/light_world.lua.git
synced 2024-12-24 20:24:19 +00:00
got rid of usedless normal maps and optimizes shadow bodies
This commit is contained in:
parent
3cafa72684
commit
7e6e3f23df
183
lib/body.lua
183
lib/body.lua
@ -3,7 +3,7 @@ local class = require(_PACKAGE.."/class")
|
|||||||
local normal_map = require(_PACKAGE..'/normal_map')
|
local normal_map = require(_PACKAGE..'/normal_map')
|
||||||
local util = require(_PACKAGE..'/util')
|
local util = require(_PACKAGE..'/util')
|
||||||
local anim8 = require(_PACKAGE..'/anim8')
|
local anim8 = require(_PACKAGE..'/anim8')
|
||||||
local vec2 = require(_PACKAGE..'/vec2')
|
local vector = require(_PACKAGE..'/vector')
|
||||||
local body = class()
|
local body = class()
|
||||||
|
|
||||||
body.glowShader = love.graphics.newShader(_PACKAGE.."/shaders/glow.glsl")
|
body.glowShader = love.graphics.newShader(_PACKAGE.."/shaders/glow.glsl")
|
||||||
@ -49,17 +49,6 @@ function body:init(id, type, ...)
|
|||||||
self.x = args[1] or 0
|
self.x = args[1] or 0
|
||||||
self.y = args[2] or 0
|
self.y = args[2] or 0
|
||||||
|
|
||||||
rectangle_canvas = love.graphics.newCanvas(args[3], args[4])
|
|
||||||
util.drawto(rectangle_canvas, 0, 0, 1, function()
|
|
||||||
love.graphics.rectangle('fill', 0, 0, args[3], args[4])
|
|
||||||
end)
|
|
||||||
self.img = love.graphics.newImage(rectangle_canvas:getImageData())
|
|
||||||
self.imgWidth = self.img:getWidth()
|
|
||||||
self.imgHeight = self.img:getHeight()
|
|
||||||
self.ix = self.imgWidth * 0.5
|
|
||||||
self.iy = self.imgHeight * 0.5
|
|
||||||
self:generateNormalMapFlat("top")
|
|
||||||
|
|
||||||
self:setShadowType('rectangle', args[3], args[4])
|
self:setShadowType('rectangle', args[3], args[4])
|
||||||
elseif self.type == "polygon" then
|
elseif self.type == "polygon" then
|
||||||
self:setPoints(...)
|
self:setPoints(...)
|
||||||
@ -73,7 +62,6 @@ function body:init(id, type, ...)
|
|||||||
self.ix = self.imgWidth * 0.5
|
self.ix = self.imgWidth * 0.5
|
||||||
self.iy = self.imgHeight * 0.5
|
self.iy = self.imgHeight * 0.5
|
||||||
end
|
end
|
||||||
self:generateNormalMapFlat("top")
|
|
||||||
self:setShadowType('rectangle', args[4] or self.imgWidth, args[5] or self.imgHeight, args[6], args[7])
|
self:setShadowType('rectangle', args[4] or self.imgWidth, args[5] or self.imgHeight, args[6], args[7])
|
||||||
self.reflective = true
|
self.reflective = true
|
||||||
elseif self.type == "animation" then
|
elseif self.type == "animation" then
|
||||||
@ -82,47 +70,29 @@ function body:init(id, type, ...)
|
|||||||
self.y = args[3] or 0
|
self.y = args[3] or 0
|
||||||
self.animations = {}
|
self.animations = {}
|
||||||
self.castsNoShadow = true
|
self.castsNoShadow = true
|
||||||
self:generateNormalMapFlat("top")
|
|
||||||
self.reflective = true
|
self.reflective = true
|
||||||
elseif self.type == "refraction" then
|
elseif self.type == "refraction" then
|
||||||
self:initNormal(...)
|
self.x = args[2] or 0
|
||||||
|
self.y = args[3] or 0
|
||||||
|
self:setNormalMap(args[1], args[4], args[5])
|
||||||
|
self.width = args[4] or self.normalWidth
|
||||||
|
self.height = args[5] or self.normalHeight
|
||||||
|
self.ox = self.width * 0.5
|
||||||
|
self.oy = self.height * 0.5
|
||||||
self.refraction = true
|
self.refraction = true
|
||||||
elseif self.type == "reflection" then
|
elseif self.type == "reflection" then
|
||||||
self:initNormal(...)
|
self.x = args[2] or 0
|
||||||
|
self.y = args[3] or 0
|
||||||
|
self:setNormalMap(args[1], args[4], args[5])
|
||||||
|
self.width = args[4] or self.normalWidth
|
||||||
|
self.height = args[5] or self.normalHeight
|
||||||
|
self.ox = self.width * 0.5
|
||||||
|
self.oy = self.height * 0.5
|
||||||
self.reflection = true
|
self.reflection = true
|
||||||
end
|
end
|
||||||
self.old_x, self.old_y = self.x, self.y
|
self.old_x, self.old_y = self.x, self.y
|
||||||
end
|
end
|
||||||
|
|
||||||
--use for refraction and reflection because they are both just a normal map
|
|
||||||
function body:initNormal(...)
|
|
||||||
local args = {...}
|
|
||||||
self.normal = args[1]
|
|
||||||
self.x = args[2] or 0
|
|
||||||
self.y = args[3] or 0
|
|
||||||
if self.normal then
|
|
||||||
self.normalWidth = self.normal:getWidth()
|
|
||||||
self.normalHeight = self.normal:getHeight()
|
|
||||||
self.width = args[4] or self.normalWidth
|
|
||||||
self.height = args[5] or self.normalHeight
|
|
||||||
self.nx = self.normalWidth * 0.5
|
|
||||||
self.ny = self.normalHeight * 0.5
|
|
||||||
self.normal:setWrap("repeat", "repeat")
|
|
||||||
self.normalVert = {
|
|
||||||
{0.0, 0.0, 0.0, 0.0},
|
|
||||||
{self.width, 0.0, 1.0, 0.0},
|
|
||||||
{self.width, self.height, 1.0, 1.0},
|
|
||||||
{0.0, self.height, 0.0, 1.0}
|
|
||||||
}
|
|
||||||
self.normalMesh = love.graphics.newMesh(self.normalVert, self.normal, "fan")
|
|
||||||
else
|
|
||||||
self.width = args[4] or 64
|
|
||||||
self.height = args[5] or 64
|
|
||||||
end
|
|
||||||
self.ox = self.width * 0.5
|
|
||||||
self.oy = self.height * 0.5
|
|
||||||
end
|
|
||||||
|
|
||||||
-- refresh
|
-- refresh
|
||||||
function body:refresh()
|
function body:refresh()
|
||||||
if self.shadowType == "rectangle" then
|
if self.shadowType == "rectangle" then
|
||||||
@ -304,26 +274,9 @@ function body:setPoints(...)
|
|||||||
-- normalize width and height
|
-- normalize width and height
|
||||||
self.width = self.width - self.x
|
self.width = self.width - self.x
|
||||||
self.height = self.height - self.y
|
self.height = self.height - self.y
|
||||||
for i = 1, #points, 2 do
|
|
||||||
points[i], points[i+1] = points[i] - self.x, points[i+1] - self.y
|
|
||||||
end
|
|
||||||
self.x = self.x + (self.width * 0.5)
|
self.x = self.x + (self.width * 0.5)
|
||||||
self.y = self.y + (self.height * 0.5)
|
self.y = self.y + (self.height * 0.5)
|
||||||
|
|
||||||
poly_canvas = love.graphics.newCanvas(self.width, self.height)
|
|
||||||
util.drawto(poly_canvas, 0, 0, 1, function()
|
|
||||||
love.graphics.polygon('fill', points)
|
|
||||||
end)
|
|
||||||
self.img = love.graphics.newImage(poly_canvas:getImageData())
|
|
||||||
self.imgWidth = self.img:getWidth()
|
|
||||||
self.imgHeight = self.img:getHeight()
|
|
||||||
self.ix = self.imgWidth * 0.5
|
|
||||||
self.iy = self.imgHeight * 0.5
|
|
||||||
self:generateNormalMapFlat("top")
|
|
||||||
--wrapping with polygon normals causes edges to show
|
|
||||||
--also we do not need wrapping for this default normal map
|
|
||||||
self.normal:setWrap("clamp", "clamp")
|
|
||||||
|
|
||||||
self:setShadowType('polygon', ...)
|
self:setShadowType('polygon', ...)
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -641,95 +594,65 @@ end
|
|||||||
--using shadow point calculations from this article
|
--using shadow point calculations from this article
|
||||||
--http://web.cs.wpi.edu/~matt/courses/cs563/talks/shadow/shadow.html
|
--http://web.cs.wpi.edu/~matt/courses/cs563/talks/shadow/shadow.html
|
||||||
function body:drawPolyShadow(light)
|
function body:drawPolyShadow(light)
|
||||||
local edgeFacingTo = {}
|
local lightPosition = vector(light.x, light.y)
|
||||||
for k = 1, #self.data, 2 do
|
local lh = lightPosition * self.zheight
|
||||||
local indexOfNextVertex = (k + 2) % #self.data
|
|
||||||
local normal = vec2(-self.data[indexOfNextVertex+1] + self.data[k + 1], self.data[indexOfNextVertex] - self.data[k]):normalize()
|
|
||||||
local lightToPoint = vec2(self.data[k] - light.x, self.data[k + 1] - light.y):normalize()
|
|
||||||
|
|
||||||
local dotProduct = normal:dot(lightToPoint)
|
|
||||||
if dotProduct > 0 then
|
|
||||||
table.insert(edgeFacingTo, true)
|
|
||||||
else
|
|
||||||
table.insert(edgeFacingTo, false)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local curShadowGeometry = {}
|
|
||||||
local lxh = (light.x * self.zheight)
|
|
||||||
local lyh = (light.y * self.zheight)
|
|
||||||
local height_diff = (self.zheight - light.z)
|
local height_diff = (self.zheight - light.z)
|
||||||
if height_diff == 0 then -- prevent inf
|
if height_diff == 0 then -- prevent inf
|
||||||
height_diff = -0.001
|
height_diff = -0.001
|
||||||
end
|
end
|
||||||
|
|
||||||
for k = 1, #edgeFacingTo do
|
for i = 1, #self.data, 2 do
|
||||||
local nextIndex = (k + 1) % #edgeFacingTo
|
local vertex = vector(self.data[i], self.data[i + 1])
|
||||||
if nextIndex == 0 then nextIndex = #edgeFacingTo end
|
local nextVertex = vector(self.data[(i + 2) % 8], self.data[(i + 2) % 8 + 1])
|
||||||
|
local startToEnd = nextVertex - vertex
|
||||||
local x, y = self.data[nextIndex*2-1], self.data[nextIndex*2]
|
if vector(startToEnd.y, -startToEnd.x) * (vertex - lightPosition) > 0 then
|
||||||
local xs, ys = (lxh - (x * light.z))/height_diff, (lyh - (y * light.z))/height_diff
|
local point1 = (lh - (vertex * light.z))/height_diff
|
||||||
|
local point2 = (lh - (nextVertex * light.z))/height_diff
|
||||||
if edgeFacingTo[k] and not edgeFacingTo[nextIndex] then
|
love.graphics.polygon("fill",
|
||||||
curShadowGeometry[#curShadowGeometry+1] = x
|
vertex.x, vertex.y, point1.x, point1.y,
|
||||||
curShadowGeometry[#curShadowGeometry+1] = y
|
point2.x, point2.y, nextVertex.x, nextVertex.y)
|
||||||
curShadowGeometry[#curShadowGeometry+1] = xs
|
|
||||||
curShadowGeometry[#curShadowGeometry+1] = ys
|
|
||||||
elseif not edgeFacingTo[k] and not edgeFacingTo[nextIndex] then
|
|
||||||
curShadowGeometry[#curShadowGeometry+1] = xs
|
|
||||||
curShadowGeometry[#curShadowGeometry+1] = ys
|
|
||||||
elseif not edgeFacingTo[k] and edgeFacingTo[nextIndex] then
|
|
||||||
curShadowGeometry[#curShadowGeometry+1] = xs
|
|
||||||
curShadowGeometry[#curShadowGeometry+1] = ys
|
|
||||||
curShadowGeometry[#curShadowGeometry+1] = x
|
|
||||||
curShadowGeometry[#curShadowGeometry+1] = y
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
if #curShadowGeometry >= 6 then
|
|
||||||
love.graphics.polygon("fill", unpack(curShadowGeometry))
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
--using shadow point calculations from this article
|
--using shadow point calculations from this article
|
||||||
--http://web.cs.wpi.edu/~matt/courses/cs563/talks/shadow/shadow.html
|
--http://web.cs.wpi.edu/~matt/courses/cs563/talks/shadow/shadow.html
|
||||||
function body:drawCircleShadow(light)
|
function body:drawCircleShadow(light)
|
||||||
local curShadowGeometry = {}
|
local selfPos = vector(self.x - self.ox, self.y - self.oy)
|
||||||
local angle = math.atan2(light.x - (self.x - self.ox), (self.y - self.oy) - light.y) + math.pi / 2
|
local lightPosition = vector(light.x, light.y)
|
||||||
local x2 = ((self.x - self.ox) + math.sin(angle) * self.radius)
|
local lh = lightPosition * self.zheight
|
||||||
local y2 = ((self.y - self.oy) - math.cos(angle) * self.radius)
|
|
||||||
local x3 = ((self.x - self.ox) - math.sin(angle) * self.radius)
|
|
||||||
local y3 = ((self.y - self.oy) + math.cos(angle) * self.radius)
|
|
||||||
|
|
||||||
local lxh = (light.x * self.zheight)
|
|
||||||
local lyh = (light.y * self.zheight)
|
|
||||||
local height_diff = (self.zheight - light.z)
|
local height_diff = (self.zheight - light.z)
|
||||||
if height_diff == 0 then -- prevent inf
|
if height_diff == 0 then -- prevent inf
|
||||||
height_diff = -0.001
|
height_diff = -0.001
|
||||||
end
|
end
|
||||||
|
|
||||||
local x4 = (lxh - (x3 * light.z))/height_diff
|
local angle = math.atan2(light.x - selfPos.x, selfPos.y - light.y) + math.pi / 2
|
||||||
local y4 = (lyh - (y3 * light.z))/height_diff
|
local point1 = vector(selfPos.x + math.sin(angle) * self.radius,
|
||||||
local x5 = (lxh - (x2 * light.z))/height_diff
|
selfPos.y - math.cos(angle) * self.radius)
|
||||||
local y5 = (lyh - (y2 * light.z))/height_diff
|
local point2 = vector(selfPos.x - math.sin(angle) * self.radius,
|
||||||
|
selfPos.y + math.cos(angle) * self.radius)
|
||||||
|
local point3 = (lh - (point1 * light.z))/height_diff
|
||||||
|
local point4 = (lh - (point2 * light.z))/height_diff
|
||||||
|
|
||||||
local radius = math.sqrt(math.pow(x5 - x4, 2) + math.pow(y5-y4, 2)) / 2
|
local radius = point3:dist(point4)/2
|
||||||
local cx, cy = (x4 + x5)/2, (y4 + y5)/2
|
local circleCenter = (point3 + point4)/2
|
||||||
local distance1 = math.sqrt(math.pow(light.x - self.x, 2) + math.pow(light.y - self.y, 2))
|
|
||||||
local distance2 = math.sqrt(math.pow(light.x - cx, 2) + math.pow(light.y - cy, 2))
|
|
||||||
|
|
||||||
if distance1 >= self.radius then
|
if lightPosition:dist(selfPos) <= self.radius then
|
||||||
love.graphics.polygon("fill", x2, y2, x3, y3, x4, y4, x5, y5)
|
love.graphics.circle("fill", circleCenter.x, circleCenter.y, radius)
|
||||||
end
|
|
||||||
|
|
||||||
if distance1 <= self.radius then
|
|
||||||
love.graphics.circle("fill", cx, cy, radius)
|
|
||||||
elseif distance2 < light.range then -- dont draw circle if way off screen
|
|
||||||
local angle1 = math.atan2(y4 - cy, x4 - cx)
|
|
||||||
local angle2 = math.atan2(y5 - cy, x5 - cx)
|
|
||||||
if angle1 > angle2 then
|
|
||||||
love.graphics.arc("fill", cx, cy, radius, angle1, angle2)
|
|
||||||
else
|
else
|
||||||
love.graphics.arc("fill", cx, cy, radius, angle1 - math.pi, angle2 - math.pi)
|
love.graphics.polygon("fill", point1.x, point1.y,
|
||||||
|
point2.x, point2.y,
|
||||||
|
point4.x, point4.y,
|
||||||
|
point3.x, point3.y)
|
||||||
|
if lightPosition:dist(circleCenter) < light.range then -- dont draw circle if way off screen
|
||||||
|
local angle1 = math.atan2(point3.y - circleCenter.y, point3.x - circleCenter.x)
|
||||||
|
local angle2 = math.atan2(point4.y - circleCenter.y, point4.x - circleCenter.x)
|
||||||
|
if angle1 < angle2 then
|
||||||
|
love.graphics.arc("fill", circleCenter.x, circleCenter.y, radius, angle1, angle2)
|
||||||
|
else
|
||||||
|
love.graphics.arc("fill", circleCenter.x, circleCenter.y, radius, angle1 - math.pi, angle2 - math.pi)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
27
lib/vec2.lua
27
lib/vec2.lua
@ -1,27 +0,0 @@
|
|||||||
local _PACKAGE = (...):match("^(.+)[%./][^%./]+") or ""
|
|
||||||
local class = require(_PACKAGE.."/class")
|
|
||||||
|
|
||||||
local vec2 = class()
|
|
||||||
|
|
||||||
function vec2:init(x, y)
|
|
||||||
self.x, self.y = x, y
|
|
||||||
end
|
|
||||||
|
|
||||||
function vec2:normalize()
|
|
||||||
local len = self:length()
|
|
||||||
return vec2(self.x / len, self.y / len)
|
|
||||||
end
|
|
||||||
|
|
||||||
function vec2:dot(v2)
|
|
||||||
return (self.x * v2.x) + (self.y * v2.y)
|
|
||||||
end
|
|
||||||
|
|
||||||
function vec2:cross(v2)
|
|
||||||
return ((self.x * v2.y) - (self.y * v2.x))
|
|
||||||
end
|
|
||||||
|
|
||||||
function vec2:length()
|
|
||||||
return math.sqrt(self:dot(self))
|
|
||||||
end
|
|
||||||
|
|
||||||
return vec2
|
|
Loading…
Reference in New Issue
Block a user