Finish up portal surface mapping
This commit is contained in:
parent
80a762eee8
commit
55411ce6e2
|
@ -245,6 +245,37 @@ function Box3.nearest_point_in_box(box, point)
|
||||||
return Vector3.min(box.max, point):max(box.min)
|
return Vector3.min(box.max, point):max(box.min)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Returns the point inside or on the box that is nearest to the given point
|
||||||
|
--- @function overlaps
|
||||||
|
--- @tparam Vector3|Box3 box_or_point
|
||||||
|
--- @treturn boolean
|
||||||
|
function Box3.overlaps(box, box_or_point)
|
||||||
|
if isVector3(box_or_point) then
|
||||||
|
return box_or_point.x >= box.min.x and box_or_point.x <= box.max.x and
|
||||||
|
box_or_point.y >= box.min.y and box_or_point.y <= box.max.y and
|
||||||
|
box_or_point.z >= box.min.z and box_or_point.z <= box.max.z
|
||||||
|
end
|
||||||
|
|
||||||
|
return box.min.x < box_or_point.max.x and box_or_point.min.x < box.max.x and
|
||||||
|
box.min.y < box_or_point.max.y and box_or_point.min.y < box.max.y and
|
||||||
|
box.min.z < box_or_point.max.z and box_or_point.min.z < box.max.z;
|
||||||
|
end
|
||||||
|
|
||||||
|
--- @function __mul
|
||||||
|
--- @tparam number|Box3
|
||||||
|
--- @treturn Box3
|
||||||
|
function Box3.__mul(a, b)
|
||||||
|
if type(a) == 'number' then
|
||||||
|
return box3(a * b.min, a * b.max)
|
||||||
|
end
|
||||||
|
|
||||||
|
if type(b) == 'number' then
|
||||||
|
return box3(a.min * b, a.max * b)
|
||||||
|
end
|
||||||
|
|
||||||
|
return box3(a.min * b.min, a.max * b.max)
|
||||||
|
end
|
||||||
|
|
||||||
--- Gets the distance from the box to the point
|
--- Gets the distance from the box to the point
|
||||||
--- If the box contains the point then the negative distance to
|
--- If the box contains the point then the negative distance to
|
||||||
--- the nearest edge is returned
|
--- the nearest edge is returned
|
||||||
|
|
|
@ -13,4 +13,6 @@ sk_definition_writer.add_definition("level", "struct LevelDefinition", "_geo", {
|
||||||
roomStaticMapping = sk_definition_writer.reference_to(static_export.room_ranges, 1),
|
roomStaticMapping = sk_definition_writer.reference_to(static_export.room_ranges, 1),
|
||||||
portalSurfaces = sk_definition_writer.reference_to(portal_surfaces.portal_surfaces, 1),
|
portalSurfaces = sk_definition_writer.reference_to(portal_surfaces.portal_surfaces, 1),
|
||||||
portalSurfaceCount = #portal_surfaces.portal_surfaces,
|
portalSurfaceCount = #portal_surfaces.portal_surfaces,
|
||||||
|
portalSurfaceMappingRange = sk_definition_writer.reference_to(portal_surfaces.portal_mapping_range, 1),
|
||||||
|
portalSurfaceMappingIndices = sk_definition_writer.reference_to(portal_surfaces.portal_mapping_data, 1),
|
||||||
})
|
})
|
|
@ -212,6 +212,22 @@ local function collision_quad_bb(collision_quad)
|
||||||
return sk_math.box3(min, max)
|
return sk_math.box3(min, max)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local INSIDE_NORMAL_TOLERANCE = 0.1
|
||||||
|
|
||||||
|
local function is_coplanar(collision_quad, mesh, relative_scale)
|
||||||
|
for _, vertex in pairs(mesh.vertices) do
|
||||||
|
local offset = vertex * relative_scale - collision_quad.corner
|
||||||
|
|
||||||
|
local z = offset:dot(collision_quad.plane.normal)
|
||||||
|
|
||||||
|
if math.abs(z) >= INSIDE_NORMAL_TOLERANCE then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
local colliders = {}
|
local colliders = {}
|
||||||
local collider_types = {}
|
local collider_types = {}
|
||||||
local collision_objects = {}
|
local collision_objects = {}
|
||||||
|
@ -258,5 +274,8 @@ sk_definition_writer.add_definition("collider_types", "struct ColliderTypeData[]
|
||||||
sk_definition_writer.add_definition("collision_objects", "struct CollisionObject[]", "_geo", collision_objects)
|
sk_definition_writer.add_definition("collision_objects", "struct CollisionObject[]", "_geo", collision_objects)
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
is_coplanar = is_coplanar,
|
||||||
|
colliders = colliders,
|
||||||
|
collision_quad_bb = collision_quad_bb,
|
||||||
collision_objects = collision_objects,
|
collision_objects = collision_objects,
|
||||||
}
|
}
|
|
@ -1,4 +1,5 @@
|
||||||
local static_export = require('tools.level_scripts.static_export')
|
local static_export = require('tools.level_scripts.static_export')
|
||||||
|
local collision_export = require('tools.level_scripts.collision_export')
|
||||||
local sk_input = require('sk_input')
|
local sk_input = require('sk_input')
|
||||||
local sk_math = require('sk_math')
|
local sk_math = require('sk_math')
|
||||||
local sk_mesh = require('sk_mesh')
|
local sk_mesh = require('sk_mesh')
|
||||||
|
@ -199,6 +200,55 @@ end
|
||||||
|
|
||||||
sk_definition_writer.add_definition("portal_surfaces", "struct PortalSurface[]", "_geo", portal_surfaces)
|
sk_definition_writer.add_definition("portal_surfaces", "struct PortalSurface[]", "_geo", portal_surfaces)
|
||||||
|
|
||||||
|
local function is_coplanar_portal_surface(quad, mesh, collision_bb)
|
||||||
|
if not mesh.material or not portalable_surfaces[mesh.material.name] then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
if not collision_export.is_coplanar(quad, mesh, sk_input.settings.model_scale) then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
local mesh_bb = mesh.bb * sk_input.settings.model_scale
|
||||||
|
|
||||||
|
if not mesh_bb:overlaps(collision_bb) then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
local portal_mapping_data = {}
|
||||||
|
local portal_mapping_range = {}
|
||||||
|
|
||||||
|
local mapping_index = 0
|
||||||
|
|
||||||
|
for _, quad in pairs(collision_export.colliders) do
|
||||||
|
local start_mapping_index = mapping_index
|
||||||
|
|
||||||
|
local collision_with_padding = collision_export.collision_quad_bb(quad)
|
||||||
|
collision_with_padding.min = collision_with_padding.min - 0.1
|
||||||
|
collision_with_padding.max = collision_with_padding.max + 0.1
|
||||||
|
|
||||||
|
for static_index, surface in pairs(static_export.static_nodes) do
|
||||||
|
if is_coplanar_portal_surface(quad, surface.mesh, collision_with_padding) then
|
||||||
|
table.insert(portal_mapping_data, static_to_portable_surface_mapping[static_index])
|
||||||
|
mapping_index = mapping_index + 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if mapping_index > 255 then
|
||||||
|
error("mapping_index was greater than 255")
|
||||||
|
end
|
||||||
|
|
||||||
|
table.insert(portal_mapping_range, {start_mapping_index, mapping_index})
|
||||||
|
end
|
||||||
|
|
||||||
|
sk_definition_writer.add_definition("mapping_indices", "u8[]", "_geo", portal_mapping_data)
|
||||||
|
sk_definition_writer.add_definition("collider_to_surface", "struct PortalSurfaceMappingRange[]", "_geo", portal_mapping_range)
|
||||||
|
|
||||||
return {
|
return {
|
||||||
portal_surfaces = portal_surfaces,
|
portal_surfaces = portal_surfaces,
|
||||||
|
portal_mapping_data = portal_mapping_data,
|
||||||
|
portal_mapping_range = portal_mapping_range,
|
||||||
}
|
}
|
Loading…
Reference in a new issue