mirror of
https://github.com/mwpenny/portal64-still-alive.git
synced 2024-10-19 22:27:36 -04:00
Add can_see argument to whitelist visible rooms
Useful for room shapes which cannot be handled by standard visibility checks. Normally this can be addressed with additional rooms and doorways, but sometimes a room is required to be a complex shape (for example, to accomodate animated static geometry). These instances should be few and far between, so leaving this as an opt-in feature that can be used during level authoring.
This commit is contained in:
parent
d5a1c302b1
commit
ab56ffb380
|
@ -18,8 +18,9 @@ Static level collision geometry. Must be a quad.
|
|||
|
||||
## Notes
|
||||
|
||||
Game objects in the same [room](./room.md) and on the same collision layer can
|
||||
collide. Some layers are also used for certain checks by the game.
|
||||
Game objects can collide if they share a collision layer. Some layers are also
|
||||
used for certain checks by the game. Static collision is only collidable if it
|
||||
is in the same [room](./room.md)
|
||||
|
||||
If no collision layers are specified, the defaults are `STATIC`, `TANGIBLE`, and
|
||||
`BLOCK_BALL`. The possible layers and their uses are as follows.
|
||||
|
|
|
@ -17,6 +17,13 @@ associated with a [door](./door.md)). If a doorway is closed, its rooms are not
|
|||
considered connected at that point (other open doorways count). Only the
|
||||
player's current room and visible connected rooms are considered for rendering.
|
||||
|
||||
Doorway visibility checks do not consider objects which may be covering a
|
||||
doorway - just that it is within the bounds of the previous doorway from the
|
||||
camera's point of view (or within the bounds of the camera itself, if there is
|
||||
no previous doorway). To block visibility in these cases, either use an
|
||||
additional room such that looking through all necessary doorways at once is
|
||||
impossible or set the room's `can_see` argument.
|
||||
|
||||
Passing through an open doorway updates an object's room index, allowing it to
|
||||
collide with other objects in the entered room while ignoring those in the
|
||||
exited room.
|
||||
|
|
|
@ -6,14 +6,15 @@ collision.
|
|||
## Name structure
|
||||
|
||||
```
|
||||
@room INDEX
|
||||
@room INDEX [can_see R1,R2,...,RN]
|
||||
```
|
||||
|
||||
## Arguments
|
||||
|
||||
| Name | Description |
|
||||
| ------- | -------------------------------------------- |
|
||||
| --------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
||||
| `INDEX` | The index number of the room the box defines |
|
||||
| `can_see R1,R2,...,RN` (optional) | If specified, rooms outside the comma-separated list will not be considered visible from the current room. This is useful for room shapes which cannot be handled by standard visibility checks. |
|
||||
|
||||
## Notes
|
||||
|
||||
|
@ -23,7 +24,7 @@ know their room index, which is updated when passing through
|
|||
[doorways](./doorway.md).
|
||||
|
||||
For performance reasons, only the player's current room and those visible
|
||||
through open doorways are considered for rendering, and only objects in the same
|
||||
room can collide with each other.
|
||||
through open doorways are considered for rendering, and objects can only collide
|
||||
with static [collision](./collision.md) in their current room.
|
||||
|
||||
Levels are limited to 64 rooms.
|
||||
|
|
|
@ -117,7 +117,7 @@ void staticRenderPopulateRooms(struct FrustumCullingInformation* cullingInfo, Mt
|
|||
|
||||
#define FORCE_RENDER_DOORWAY_DISTANCE 0.1f
|
||||
|
||||
void staticRenderDetermineVisibleRooms(struct FrustumCullingInformation* cullingInfo, u16 currentRoom, u64* visitedRooms) {
|
||||
void staticRenderDetermineVisibleRooms(struct FrustumCullingInformation* cullingInfo, u16 currentRoom, u64* visitedRooms, u64 nonVisibleRooms) {
|
||||
if (currentRoom == RIGID_BODY_NO_ROOM) {
|
||||
return;
|
||||
}
|
||||
|
@ -125,6 +125,8 @@ void staticRenderDetermineVisibleRooms(struct FrustumCullingInformation* culling
|
|||
u64 roomMask = 1LL << currentRoom;
|
||||
*visitedRooms |= roomMask;
|
||||
|
||||
nonVisibleRooms |= gCurrentLevel->world.rooms[currentRoom].nonVisibleRooms;
|
||||
|
||||
for (int i = 0; i < gCurrentLevel->world.rooms[currentRoom].doorwayCount; ++i) {
|
||||
struct Doorway* doorway = &gCurrentLevel->world.doorways[gCurrentLevel->world.rooms[currentRoom].doorwayIndices[i]];
|
||||
|
||||
|
@ -133,7 +135,8 @@ void staticRenderDetermineVisibleRooms(struct FrustumCullingInformation* culling
|
|||
}
|
||||
|
||||
int newRoom = currentRoom == doorway->roomA ? doorway->roomB : doorway->roomA;
|
||||
if (*visitedRooms & (1LL << newRoom)) {
|
||||
u64 newRoomMask = 1LL << newRoom;
|
||||
if ((*visitedRooms & newRoomMask) || (nonVisibleRooms & newRoomMask)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -154,7 +157,7 @@ void staticRenderDetermineVisibleRooms(struct FrustumCullingInformation* culling
|
|||
struct FrustumCullingInformation doorwayFrustum;
|
||||
frustumFromQuad(&cullingInfo->cameraPos, &doorway->quad, &doorwayFrustum);
|
||||
|
||||
staticRenderDetermineVisibleRooms(&doorwayFrustum, newRoom, visitedRooms);
|
||||
staticRenderDetermineVisibleRooms(&doorwayFrustum, newRoom, visitedRooms, nonVisibleRooms);
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
#include "scene/camera.h"
|
||||
#include "../scene/dynamic_render_list.h"
|
||||
|
||||
void staticRenderDetermineVisibleRooms(struct FrustumCullingInformation* cullingInfo, u16 currentRoom, u64* visitedRooms);
|
||||
void staticRenderDetermineVisibleRooms(struct FrustumCullingInformation* cullingInfo, u16 currentRoom, u64* visitedRooms, u64 nonVisibleRooms);
|
||||
int staticRenderIsRoomVisible(u64 visibleRooms, u16 roomIndex);
|
||||
void staticRender(struct Transform* cameraTransform, struct FrustumCullingInformation* cullingInfo, u64 visibleRooms, struct DynamicRenderDataList* dynamicList, int stageIndex, Mtx* staticMatrices, struct Transform* staticTransforms, struct RenderState* renderState);
|
||||
|
||||
|
|
|
@ -29,6 +29,8 @@ struct Room {
|
|||
|
||||
short* doorwayIndices;
|
||||
short doorwayCount;
|
||||
|
||||
u64 nonVisibleRooms;
|
||||
};
|
||||
|
||||
struct World {
|
||||
|
|
|
@ -370,7 +370,7 @@ int renderShouldRenderOtherPortal(struct Scene* scene, int visiblePortal, struct
|
|||
}
|
||||
|
||||
void renderPlanFinishView(struct RenderPlan* renderPlan, struct Scene* scene, struct RenderProps* properties, struct RenderState* renderState) {
|
||||
staticRenderDetermineVisibleRooms(&properties->cameraMatrixInfo.cullingInformation, properties->fromRoom, &properties->visiblerooms);
|
||||
staticRenderDetermineVisibleRooms(&properties->cameraMatrixInfo.cullingInformation, properties->fromRoom, &properties->visiblerooms, 0);
|
||||
|
||||
struct Ray cameraRay;
|
||||
quatMultVector(&properties->camera.transform.rotation, &gForward, &cameraRay.dir);
|
||||
|
|
|
@ -1,14 +1,29 @@
|
|||
|
||||
local sk_scene = require('sk_scene')
|
||||
local sk_math = require('sk_math')
|
||||
local util = require('tools.level_scripts.util')
|
||||
|
||||
local room_blocks = {}
|
||||
local room_count = 0
|
||||
local room_bb = {}
|
||||
local room_non_visibility = {}
|
||||
|
||||
for _, room in pairs(sk_scene.nodes_for_type("@room")) do
|
||||
local firstMesh = room.node.meshes[1]:transform(room.node.full_transformation)
|
||||
local room_index = tonumber(room.arguments[1])
|
||||
local non_visible_rooms = 0
|
||||
|
||||
local can_see = sk_scene.find_named_argument(room.arguments, "can_see")
|
||||
if can_see then
|
||||
local visible_rooms = 1 << room_index
|
||||
|
||||
local can_see_rooms = util.string_split(util.trim(can_see), ',')
|
||||
for _, can_see_index in pairs(can_see_rooms) do
|
||||
visible_rooms = visible_rooms | (1 << tonumber(can_see_index))
|
||||
end
|
||||
|
||||
non_visible_rooms = ~visible_rooms
|
||||
end
|
||||
|
||||
room_count = math.max(room_count, room_index + 1)
|
||||
|
||||
|
@ -18,6 +33,12 @@ for _, room in pairs(sk_scene.nodes_for_type("@room")) do
|
|||
room_bb[room_index + 1] = firstMesh.bb
|
||||
end
|
||||
|
||||
if room_non_visibility[room_index + 1] then
|
||||
room_non_visibility[room_index + 1] = room_non_visibility[room_index + 1] | non_visible_rooms
|
||||
else
|
||||
room_non_visibility[room_index + 1] = non_visible_rooms
|
||||
end
|
||||
|
||||
table.insert(room_blocks, {
|
||||
bb = firstMesh.bb,
|
||||
room_index = room_index,
|
||||
|
@ -63,4 +84,5 @@ return {
|
|||
node_nearest_room_index = node_nearest_room_index,
|
||||
room_count = room_count,
|
||||
room_bb = room_bb,
|
||||
room_non_visibility = room_non_visibility,
|
||||
}
|
|
@ -128,6 +128,7 @@ local function generate_room(room_index)
|
|||
room_export.room_bb[room_index] or sk_math.box3(),
|
||||
sk_definition_writer.reference_to(room_doorways[room_index], 1),
|
||||
#room_doorways[room_index],
|
||||
room_export.room_non_visibility[room_index]
|
||||
}
|
||||
end
|
||||
|
||||
|
|
Loading…
Reference in a new issue