Only offset portal surface when trying decals are on the same surface
This commit is contained in:
parent
5c345c25d8
commit
516b30b0b4
|
@ -316,7 +316,7 @@ 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
|
||||
--- Returns true of the two bounding boxes have some volume in common
|
||||
--- @function overlaps
|
||||
--- @tparam Vector3|Box3 box_or_point
|
||||
--- @treturn boolean
|
||||
|
|
|
@ -51,6 +51,8 @@ void sceneSerializePortals(struct Serializer* serializer, SerializeAction action
|
|||
}
|
||||
}
|
||||
|
||||
#define PORTAL_FLAGS_TO_DESERIALIZE (PortalFlagsPlayerPortal | PortalFlagsZOffset)
|
||||
|
||||
void sceneDeserializePortals(struct Serializer* serializer, struct Scene* scene) {
|
||||
for (int portalIndex = 0; portalIndex < 2; ++portalIndex) {
|
||||
char flags;
|
||||
|
@ -98,11 +100,8 @@ void sceneDeserializePortals(struct Serializer* serializer, struct Scene* scene)
|
|||
collisionSceneSetPortal(portalIndex, &portal->rigidBody.transform, roomIndex, colliderIndex);
|
||||
collisionObjectUpdateBB(&portal->collisionObject);
|
||||
|
||||
if (flags & PortalFlagsPlayerPortal) {
|
||||
portal->flags |= PortalFlagsPlayerPortal;
|
||||
} else {
|
||||
portal->flags &= ~PortalFlagsPlayerPortal;
|
||||
}
|
||||
portal->flags &= ~PORTAL_FLAGS_TO_DESERIALIZE;
|
||||
portal->flags |= PORTAL_FLAGS_TO_DESERIALIZE & flags;
|
||||
|
||||
portal->opacity = 0.0f;
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
enum PortalFlags {
|
||||
PortalFlagsOddParity = (1 << 0),
|
||||
PortalFlagsPlayerPortal = (1 << 2),
|
||||
PortalFlagsZOffset = (1 << 3),
|
||||
};
|
||||
|
||||
struct Portal {
|
||||
|
|
|
@ -27,6 +27,7 @@ struct PortalSurface {
|
|||
u8 edgeCount;
|
||||
u8 vertexCount;
|
||||
u8 shouldCleanup;
|
||||
u8 hasDecals;
|
||||
|
||||
struct Vector3 right;
|
||||
struct Vector3 up;
|
||||
|
|
|
@ -563,13 +563,15 @@ void renderPlanExecute(struct RenderPlan* renderPlan, struct Scene* scene, Mtx*
|
|||
faceModel = portal_portal_orange_face_model_gfx;
|
||||
portalModel = portal_portal_orange_model_gfx;
|
||||
}
|
||||
|
||||
// render the portal cover with a slightly offset z
|
||||
// so it doesn't z fight with the surface it is attached to
|
||||
Vp* vpWithOffset = renderStateRequestViewport(renderState);
|
||||
*vpWithOffset = *current->viewport;
|
||||
vpWithOffset->vp.vtrans[2] -= 1;
|
||||
gSPViewport(renderState->dl++, vpWithOffset);
|
||||
|
||||
if (portal->flags & PortalFlagsZOffset) {
|
||||
// render the portal cover with a slightly offset z
|
||||
// so it doesn't z fight with the surface it is attached to
|
||||
Vp* vpWithOffset = renderStateRequestViewport(renderState);
|
||||
*vpWithOffset = *current->viewport;
|
||||
vpWithOffset->vp.vtrans[2] -= 2;
|
||||
gSPViewport(renderState->dl++, vpWithOffset);
|
||||
}
|
||||
gSPDisplayList(renderState->dl++, faceModel);
|
||||
gSPViewport(renderState->dl++, current->viewport);
|
||||
if (current->previousProperties == NULL && portalIndex == renderPlan->clippedPortalIndex && renderPlan->nearPolygonCount) {
|
||||
|
|
|
@ -860,6 +860,12 @@ int sceneOpenPortal(struct Scene* scene, struct Transform* at, int transformInde
|
|||
portal->flags &= ~PortalFlagsPlayerPortal;
|
||||
}
|
||||
|
||||
if (existingSurface->hasDecals) {
|
||||
portal->flags |= PortalFlagsZOffset;
|
||||
} else {
|
||||
portal->flags &= ~PortalFlagsZOffset;
|
||||
}
|
||||
|
||||
if (collisionSceneIsPortalOpen()) {
|
||||
// the second portal is fully transparent right away
|
||||
portal->opacity = 0.0f;
|
||||
|
|
|
@ -58,7 +58,7 @@ local function get_edge_index(edges, edge_key)
|
|||
return 0xFF
|
||||
end
|
||||
|
||||
local function calculate_portal_single_surface(mesh, mesh_display_list)
|
||||
local function calculate_portal_single_surface(mesh, mesh_display_list, has_decals)
|
||||
local origin = mesh.bb:lerp(0.5)
|
||||
|
||||
local right, up, normal = calculate_surface_basis(mesh)
|
||||
|
@ -129,6 +129,7 @@ local function calculate_portal_single_surface(mesh, mesh_display_list)
|
|||
edgeCount = #edges,
|
||||
vertexCount = #vertices,
|
||||
shouldCleanup = 0,
|
||||
hasDecals = has_decals,
|
||||
|
||||
right = right,
|
||||
up = up,
|
||||
|
@ -142,7 +143,7 @@ end
|
|||
for _, surface in pairs(static_export.static_nodes) do
|
||||
if surface.accept_portals then
|
||||
table.insert(static_to_portable_surface_mapping, #portal_surfaces)
|
||||
table.insert(portal_surfaces, calculate_portal_single_surface(surface.mesh, surface.display_list))
|
||||
table.insert(portal_surfaces, calculate_portal_single_surface(surface.mesh, surface.display_list, surface.has_decals))
|
||||
else
|
||||
table.insert(static_to_portable_surface_mapping, -1)
|
||||
end
|
||||
|
|
|
@ -33,7 +33,7 @@ local function is_coplanar(mesh, plane)
|
|||
end
|
||||
|
||||
local function should_join_mesh(entry)
|
||||
return entry.plane ~= nil
|
||||
return entry.should_join_mesh
|
||||
end
|
||||
|
||||
local function bb_union_cost(a, b)
|
||||
|
@ -76,6 +76,28 @@ local function bb_list(bb)
|
|||
}
|
||||
end
|
||||
|
||||
local function check_for_decals(portal_surface, all_static_ndes)
|
||||
if not portal_surface.accept_portals then
|
||||
return false
|
||||
end
|
||||
|
||||
local box_with_padding = sk_math.box3(portal_surface.original_bb.min - 0.1, portal_surface.original_bb.max + 0.1)
|
||||
|
||||
for _, other in pairs(all_static_ndes) do
|
||||
local material = other.chunk.mesh.material
|
||||
|
||||
if material.renderMode and
|
||||
material.renderMode.zMode == "ZMODE_DEC" and
|
||||
portal_surface.transform_index == other.transform_index and
|
||||
is_coplanar(other.chunk.mesh, portal_surface.plane) and
|
||||
box_with_padding:overlaps(other.original_bb) then
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
return false
|
||||
end
|
||||
|
||||
local function list_static_nodes(nodes)
|
||||
local result = {}
|
||||
local bb_scale = sk_input.settings.fixed_point_scale
|
||||
|
@ -100,10 +122,11 @@ local function list_static_nodes(nodes)
|
|||
end
|
||||
|
||||
local plane = sk_math.plane3_with_point(chunkV.mesh.normals[1], chunkV.mesh.vertices[1])
|
||||
local accept_portals =chunkV.mesh.material and portalable_surfaces[chunkV.mesh.material.name] and not sk_scene.find_flag_argument(v.arguments, "no_portals")
|
||||
local should_join_mesh = true
|
||||
local accept_portals = chunkV.mesh.material and portalable_surfaces[chunkV.mesh.material.name] and not sk_scene.find_flag_argument(v.arguments, "no_portals")
|
||||
|
||||
if transform_index or signal or accept_portals or not is_coplanar(chunkV.mesh, plane) then
|
||||
plane = nil
|
||||
should_join_mesh = false
|
||||
end
|
||||
|
||||
insert_or_merge(result, {
|
||||
|
@ -113,13 +136,19 @@ local function list_static_nodes(nodes)
|
|||
transform_index = transform_index,
|
||||
room_index = room_export.node_nearest_room_index(v.node) or 0,
|
||||
accept_portals = accept_portals,
|
||||
has_decals = false,
|
||||
signal = signal,
|
||||
original_bb = original_bb,
|
||||
plane = plane,
|
||||
should_join_mesh = should_join_mesh,
|
||||
})
|
||||
end
|
||||
end
|
||||
|
||||
for _, node in pairs(result) do
|
||||
node.has_decals = check_for_decals(node, result)
|
||||
end
|
||||
|
||||
return result;
|
||||
end
|
||||
|
||||
|
@ -320,6 +349,7 @@ local function process_static_nodes(nodes)
|
|||
transform_index = source_node.transform_index,
|
||||
room_index = source_node.room_index,
|
||||
accept_portals = source_node.accept_portals,
|
||||
has_decals = source_node.has_decals,
|
||||
signal = source_node.signal,
|
||||
})
|
||||
end
|
||||
|
|
Loading…
Reference in a new issue