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)
|
||||
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
|
||||
--- If the box contains the point then the negative distance to
|
||||
--- 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),
|
||||
portalSurfaces = sk_definition_writer.reference_to(portal_surfaces.portal_surfaces, 1),
|
||||
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)
|
||||
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 collider_types = {}
|
||||
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)
|
||||
|
||||
return {
|
||||
is_coplanar = is_coplanar,
|
||||
colliders = colliders,
|
||||
collision_quad_bb = collision_quad_bb,
|
||||
collision_objects = collision_objects,
|
||||
}
|
|
@ -1,4 +1,5 @@
|
|||
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_math = require('sk_math')
|
||||
local sk_mesh = require('sk_mesh')
|
||||
|
@ -199,6 +200,55 @@ end
|
|||
|
||||
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 {
|
||||
portal_surfaces = portal_surfaces,
|
||||
portal_mapping_data = portal_mapping_data,
|
||||
portal_mapping_range = portal_mapping_range,
|
||||
}
|
Loading…
Reference in a new issue