mirror of
https://github.com/mwpenny/portal64-still-alive.git
synced 2024-11-30 07:40:44 +00:00
Work on static lighting code
This commit is contained in:
parent
57e4544fee
commit
0e2a45665d
@ -325,6 +325,13 @@ function Box3.lerp(box, lerp)
|
||||
return Vector3.lerp(box.min, box.max, lerp)
|
||||
end
|
||||
|
||||
--- Finds a lerp value, x, such that box:lerp(x) == pos
|
||||
--- @function pos
|
||||
--- @treturn Vector3
|
||||
function Box3.unlerp(box, pos)
|
||||
return (pos - box.min) / (box.max - box.min)
|
||||
end
|
||||
|
||||
|
||||
--- Linearly interpolates between the min and max of the box
|
||||
--- @function union
|
||||
@ -436,6 +443,102 @@ local function isColor4(obj)
|
||||
return type(obj) == 'table' and type(obj.r) == 'number' and type(obj.g) == 'number' and type(obj.b) == 'number' and type(obj.a) == 'number'
|
||||
end
|
||||
|
||||
--- @type Color4
|
||||
--- @tfield number r
|
||||
--- @tfield number g
|
||||
--- @tfield number b
|
||||
--- @tfield number a
|
||||
Color4.__index = Color4;
|
||||
|
||||
|
||||
--- @function __eq
|
||||
--- @tparam number|Color4 b
|
||||
--- @treturn Color4
|
||||
function Color4.__eq(a, b)
|
||||
if (type(a) == 'number') then
|
||||
return a == b.r and a == b.g and a == b.b and a == b.a
|
||||
end
|
||||
|
||||
if (type(b) == 'number') then
|
||||
return a.r == b and a.g == b and a.b + b and a.a == b
|
||||
end
|
||||
|
||||
if (not isColor4(b)) then
|
||||
error('Color4.__eq expected another vector as second operand', 2)
|
||||
end
|
||||
|
||||
return a.r == b.r and a.g == b.g and a.b == b.b and a.a == a.a
|
||||
end
|
||||
|
||||
--- @function __add
|
||||
--- @tparam number|Color4 b
|
||||
--- @treturn Color4
|
||||
function Color4.__add(a, b)
|
||||
if (type(a) == 'number') then
|
||||
return color4(a + b.r, a + b.g, a + b.b, a + b.a)
|
||||
end
|
||||
|
||||
if (type(b) == 'number') then
|
||||
return color4(a.r + b, a.g + b, a.b + b, a.a + b)
|
||||
end
|
||||
|
||||
if (not isColor4(b)) then
|
||||
error('Color4.__add expected another vector as second operand got ' .. type(b), 2)
|
||||
end
|
||||
|
||||
return color4(a.r + b.r, a.g + b.g, a.b + b.b, a.a + b.a)
|
||||
end
|
||||
|
||||
--- @function __sub
|
||||
--- @tparam number|Color4 b
|
||||
--- @treturn Color4
|
||||
function Color4.__sub(a, b)
|
||||
if (type(a) == 'number') then
|
||||
return color4(a - b.r, a - b.g, a - b.b, a - b.a)
|
||||
end
|
||||
|
||||
if (type(b) == 'number') then
|
||||
return color4(a.r - b, a.g - b, a.b - b, a.a - b)
|
||||
end
|
||||
|
||||
if (not isColor4(b)) then
|
||||
error('Color4.__sub expected another vector as second operand', 2)
|
||||
end
|
||||
|
||||
if (a == nil) then
|
||||
print(debug.traceback())
|
||||
end
|
||||
|
||||
return color4(a.r - b.r, a.g - b.g, a.b - b.b, a.a - b.a)
|
||||
end
|
||||
|
||||
--- @function __mul
|
||||
--- @tparam number|Color4 b
|
||||
--- @treturn Color4
|
||||
function Color4.__mul(a, b)
|
||||
if (type(a) == 'number') then
|
||||
return color4(a * b.r, a * b.g, a * b.b, a * b.a)
|
||||
end
|
||||
|
||||
if (type(b) == 'number') then
|
||||
return color4(a.r * b, a.g * b, a.b * b, a.a * b)
|
||||
end
|
||||
|
||||
if (not isColor4(b)) then
|
||||
error('Color4.__mul expected another vector or number as second operand got ' .. type(b), 2)
|
||||
end
|
||||
|
||||
return color4(a.r * b.r, a.g * b.g, a.b * b.b, a.a * b.a)
|
||||
end
|
||||
|
||||
--- Linearly interpolates between two points
|
||||
--- @function lerp
|
||||
--- @tparam Color4 b
|
||||
--- @treturn Color4
|
||||
function Color4.lerp(a, b, lerp)
|
||||
return a * (1 - lerp) + b * lerp
|
||||
end
|
||||
|
||||
return {
|
||||
vector3 = vector3,
|
||||
Vector3 = Vector3,
|
||||
|
@ -219,10 +219,17 @@ void meshToLua(lua_State* L, std::shared_ptr<ExtendedMesh> mesh) {
|
||||
toLua(L, mesh->mMesh->mFaces, mesh->mMesh->mNumFaces);
|
||||
lua_setfield(L, -2, "faces");
|
||||
|
||||
if (mesh->mMesh->mColors[0]) {
|
||||
toLuaLazyArray<aiColor4D>(L, mesh->mMesh->mColors[0], mesh->mMesh->mNumVertices);
|
||||
} else {
|
||||
lua_pushnil(L);
|
||||
lua_createtable(L, AI_MAX_NUMBER_OF_COLOR_SETS, 0);
|
||||
for (int i = 0; i < AI_MAX_NUMBER_OF_COLOR_SETS; ++i) {
|
||||
if (!mesh->mMesh->mColors[i]) {
|
||||
mesh->mMesh->mColors[i] = new aiColor4D[mesh->mMesh->mNumVertices];
|
||||
|
||||
for (unsigned vertexIndex = 0; vertexIndex < mesh->mMesh->mNumVertices; ++vertexIndex) {
|
||||
mesh->mMesh->mColors[i][vertexIndex] = aiColor4D(1.0, 1.0, 1.0, 1.0);
|
||||
}
|
||||
}
|
||||
toLuaLazyArray<aiColor4D>(L, mesh->mMesh->mColors[i], mesh->mMesh->mNumVertices);
|
||||
lua_seti(L, -2, i + 1);
|
||||
}
|
||||
lua_setfield(L, -2, "colors");
|
||||
|
||||
|
@ -10,6 +10,7 @@ local entities = require('tools.level_scripts.entities')
|
||||
local signals = require('tools.level_scripts.signals')
|
||||
local animation = require('tools.level_scripts.animation')
|
||||
local dynamic_collision = require('tools.level_scripts.dynamic_collision_export')
|
||||
local static_lighting = require('tools.level_scripts.static_lighting')
|
||||
|
||||
sk_definition_writer.add_definition("level", "struct LevelDefinition", "_geo", {
|
||||
collisionQuads = sk_definition_writer.reference_to(collision_export.collision_objects, 1),
|
||||
|
134
tools/level_scripts/static_lighting.lua
Normal file
134
tools/level_scripts/static_lighting.lua
Normal file
@ -0,0 +1,134 @@
|
||||
|
||||
local sk_scene = require('sk_scene')
|
||||
local sk_math = require('sk_math');
|
||||
|
||||
local ambient_nodes = sk_scene.nodes_for_type('@ambient')
|
||||
|
||||
local ambient_blocks = {}
|
||||
|
||||
local function build_ambient_block(ambient_mesh)
|
||||
local midpoint = sk_math.vector3(0, 0, 0)
|
||||
local min = ambient_mesh.vertices[1]
|
||||
local max = ambient_mesh.vertices[1]
|
||||
|
||||
for _, vector in pairs(ambient_mesh.vertices) do
|
||||
midpoint = midpoint + vector
|
||||
min = min:min(vector)
|
||||
max = max:max(vector)
|
||||
end
|
||||
|
||||
midpoint = midpoint * (1 / #ambient_mesh.vertices)
|
||||
|
||||
local colors = {}
|
||||
|
||||
for index, vector in pairs(ambient_mesh.vertices) do
|
||||
local corner_index = 1
|
||||
|
||||
if (vector.x > midpoint.x) then
|
||||
corner_index = corner_index + 1
|
||||
end
|
||||
|
||||
if (vector.y > midpoint.y) then
|
||||
corner_index = corner_index + 2
|
||||
end
|
||||
|
||||
if (vector.z > midpoint.z) then
|
||||
corner_index = corner_index + 4
|
||||
end
|
||||
|
||||
colors[corner_index] = ambient_mesh.colors[1] and ambient_mesh.colors[1][index]
|
||||
end
|
||||
|
||||
return {
|
||||
bb = sk_math.box3(min, max),
|
||||
colors = colors,
|
||||
}
|
||||
end
|
||||
|
||||
local function evaluate_ambient_block(block, pos, normal)
|
||||
local lerp_values = block.bb:unlerp(pos)
|
||||
|
||||
local x0 = block.colors[1]:lerp(block.colors[2], lerp_values.x)
|
||||
local x1 = block.colors[3]:lerp(block.colors[4], lerp_values.x)
|
||||
local x2 = block.colors[5]:lerp(block.colors[6], lerp_values.x)
|
||||
local x3 = block.colors[7]:lerp(block.colors[8], lerp_values.x)
|
||||
|
||||
local y0 = x0:lerp(x1, lerp_values.y)
|
||||
local y1 = x2:lerp(x3, lerp_values.y)
|
||||
|
||||
return y0:lerp(y1, lerp_values.z)
|
||||
end
|
||||
|
||||
for index, ambient_node in pairs(ambient_nodes) do
|
||||
for _, mesh in pairs(ambient_node.node.meshes) do
|
||||
local global_mesh = mesh:transform(ambient_node.node.full_transformation)
|
||||
|
||||
table.insert(ambient_blocks, build_ambient_block(global_mesh))
|
||||
end
|
||||
end
|
||||
|
||||
local function find_nearest_ambient_boxes(pos, max_count)
|
||||
local boxes = {};
|
||||
local distances = {};
|
||||
|
||||
for _, ambient_block in pairs(ambient_blocks) do
|
||||
local distance = ambient_block.bb:distance_to_point(pos)
|
||||
|
||||
-- if inside a block just return it
|
||||
if distance <= 0 then
|
||||
return {ambient_block}, {1}
|
||||
end
|
||||
|
||||
local insert_index = #boxes + 1
|
||||
|
||||
for index, other_distance in pairs(distances) do
|
||||
if distance < other_distance then
|
||||
insert_index = index
|
||||
end
|
||||
end
|
||||
|
||||
if insert_index < max_count then
|
||||
table.insert(boxes, insert_index, ambient_block)
|
||||
table.insert(distances, insert_index, distance)
|
||||
|
||||
if #boxes > max_count then
|
||||
table.remove(boxes)
|
||||
table.remove(distances)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local weights = {}
|
||||
local total_weight = 0
|
||||
|
||||
for index, distance in pairs(distances) do
|
||||
total_weight = total_weight + distance
|
||||
weights[index] = distance
|
||||
end
|
||||
|
||||
for index, _ in pairs(weights) do
|
||||
weights[index] = 1 - weights[index] / total_weight
|
||||
end
|
||||
|
||||
return boxes, weights
|
||||
end
|
||||
|
||||
local function light_vertex(pos, normal)
|
||||
local boxes, weights = find_nearest_ambient_boxes(pos, 2)
|
||||
|
||||
if #boxes == 0 then
|
||||
return sk_math.color4(1, 1, 1, 1)
|
||||
end
|
||||
|
||||
local result = sk_math.color4(0, 0, 0, 0)
|
||||
|
||||
for index, block in pairs(boxes) do
|
||||
result = result + evaluate_ambient_block(block, pos, normal) * weights[index]
|
||||
end
|
||||
|
||||
return result
|
||||
end
|
||||
|
||||
return {
|
||||
light_vertex = light_vertex,
|
||||
}
|
Loading…
Reference in New Issue
Block a user