Animated surfaces can now recieve portals

This commit is contained in:
James Lambert 2023-01-04 08:39:08 -07:00
parent 26db9cf101
commit 45e6194bd0
6 changed files with 104 additions and 15 deletions

View file

@ -214,6 +214,8 @@ struct LevelDefinition {
struct PortalSurface* portalSurfaces;
// maps index of a collisionQuads to indices in portalSurfaces
struct PortalSurfaceMappingRange* portalSurfaceMappingRange;
struct DynamicBoxDefinition* dynamicBoxes;
struct PortalSurfaceMappingRange* portalSurfaceDynamicMappingRange;
u8* portalSurfaceMappingIndices;
struct Trigger* triggers;
struct Cutscene* cutscenes;
@ -230,10 +232,10 @@ struct LevelDefinition {
struct BoxDropperDefinition* boxDroppers;
struct AnimationInfo* animations;
struct SwitchDefinition* switches;
struct DynamicBoxDefinition* dynamicBoxes;
short collisionQuadCount;
short staticContentCount;
short portalSurfaceCount;
short dynamicBoxCount;
short triggerCount;
short cutsceneCount;
short locationCount;
@ -248,7 +250,6 @@ struct LevelDefinition {
short boxDropperCount;
short animationInfoCount;
short switchCount;
short dynamicBoxCount;
short startLocation;
};

View file

@ -55,6 +55,7 @@ struct LevelDefinition* levelFixPointers(struct LevelDefinition* from, int point
}
result->portalSurfaceMappingRange = ADJUST_POINTER_POS(result->portalSurfaceMappingRange, pointerOffset);
result->portalSurfaceDynamicMappingRange = ADJUST_POINTER_POS(result->portalSurfaceDynamicMappingRange, pointerOffset);
result->portalSurfaceMappingIndices = ADJUST_POINTER_POS(result->portalSurfaceMappingIndices, pointerOffset);
result->triggers = ADJUST_POINTER_POS(result->triggers, pointerOffset);
result->cutscenes = ADJUST_POINTER_POS(result->cutscenes, pointerOffset);

View file

@ -51,7 +51,7 @@ void sceneInitDynamicColliders(struct Scene* scene) {
colliderType[i].bounce = 0.5f;
colliderType[i].friction = 0.5f;
colliderType[i].callbacks = &gCollisionBoxCallbacks;
collisionObjectInit(&colliders[i], &colliderType[i], &body[i], 1.0f, COLLISION_LAYERS_TANGIBLE);
collisionObjectInit(&colliders[i], &colliderType[i], &body[i], 1.0f, COLLISION_LAYERS_TANGIBLE | COLLISION_LAYERS_STATIC);
rigidBodyMarkKinematic(&body[i]);
body[i].currentRoom = gCurrentLevel->dynamicBoxes[i].roomIndex;
@ -446,7 +446,18 @@ void sceneUpdate(struct Scene* scene) {
}
}
int sceneOpenPortal(struct Scene* scene, struct Transform* at, int portalIndex, struct PortalSurfaceMappingRange surfaceMapping, struct CollisionObject* collisionObject, int roomIndex) {
int sceneOpenPortal(struct Scene* scene, struct Transform* at, struct Transform* relativeTo, int portalIndex, struct PortalSurfaceMappingRange surfaceMapping, struct CollisionObject* collisionObject, int roomIndex) {
struct Transform finalAt;
if (relativeTo) {
struct Transform relativeInverse;
struct Transform relativePreScale = *relativeTo;
vector3Scale(&relativePreScale.position, &relativePreScale.position, 1.0f / SCENE_SCALE);
transformInvert(&relativePreScale, &relativeInverse);
transformConcat(&relativeInverse, at, &finalAt);
} else {
finalAt = *at;
}
for (int indexIndex = surfaceMapping.minPortalIndex; indexIndex < surfaceMapping.maxPortalIndex; ++indexIndex) {
int surfaceIndex = gCurrentLevel->portalSurfaceMappingIndices[indexIndex];
@ -455,10 +466,18 @@ int sceneOpenPortal(struct Scene* scene, struct Transform* at, int portalIndex,
struct Portal* portal = &scene->portals[portalIndex];
if (portalAttachToSurface(portal, existingSurface, surfaceIndex, at)) {
if (portalAttachToSurface(portal, existingSurface, surfaceIndex, &finalAt)) {
soundPlayerPlay(soundsPortalOpen2, 1.0f, 1.0f, &at->position);
// the portal position may have been adjusted
if (relativeTo) {
struct Transform relativePreScale = *relativeTo;
vector3Scale(&relativePreScale.position, &relativePreScale.position, 1.0f / SCENE_SCALE);
transformConcat(&relativePreScale, &finalAt, &portal->transform);
} else {
portal->transform = finalAt;
}
portal->transform = *at;
portal->roomIndex = roomIndex;
portal->scale = 0.0f;
gCollisionScene.portalTransforms[portalIndex] = &portal->transform;
@ -477,6 +496,34 @@ int sceneOpenPortal(struct Scene* scene, struct Transform* at, int portalIndex,
return 0;
}
int sceneDynamicBoxIndex(struct Scene* scene, struct CollisionObject* hitObject) {
if (hitObject < scene->dynamicColliders || hitObject >= scene->dynamicColliders + gCurrentLevel->dynamicBoxCount) {
return -1;
}
return hitObject - scene->dynamicColliders;
}
int sceneDetermineSurfaceMapping(struct Scene* scene, struct CollisionObject* hitObject, struct PortalSurfaceMappingRange* mappingRangeOut, struct Transform** relativeToOut) {
int quadIndex = levelQuadIndex(hitObject);
if (quadIndex != -1) {
*mappingRangeOut = gCurrentLevel->portalSurfaceMappingRange[quadIndex];
*relativeToOut = NULL;
return 1;
}
int dynamicBoxIndex = sceneDynamicBoxIndex(scene, hitObject);
if (dynamicBoxIndex != -1) {
*mappingRangeOut = gCurrentLevel->portalSurfaceDynamicMappingRange[dynamicBoxIndex];
*relativeToOut = sceneAnimatorTransformForIndex(&scene->animator, gCurrentLevel->dynamicBoxes[dynamicBoxIndex].transformIndex);
return 1;
}
return 0;
}
int sceneFirePortal(struct Scene* scene, struct Ray* ray, struct Vector3* playerUp, int portalIndex, int roomIndex) {
struct RaycastHit hit;
@ -484,9 +531,10 @@ int sceneFirePortal(struct Scene* scene, struct Ray* ray, struct Vector3* player
return 0;
}
int quadIndex = levelQuadIndex(hit.object);
struct PortalSurfaceMappingRange mappingRange;
struct Transform* relativeTo = NULL;
if (quadIndex == -1) {
if (!sceneDetermineSurfaceMapping(scene, hit.object, &mappingRange, &relativeTo)) {
return 0;
}
@ -514,7 +562,7 @@ int sceneFirePortal(struct Scene* scene, struct Ray* ray, struct Vector3* player
quatLook(&hitDirection, &upDir, &portalLocation.rotation);
}
return sceneOpenPortal(scene, &portalLocation, portalIndex, gCurrentLevel->portalSurfaceMappingRange[quadIndex], &gCurrentLevel->collisionQuads[quadIndex], hit.roomIndex);
return sceneOpenPortal(scene, &portalLocation, relativeTo, portalIndex, mappingRange, hit.object, hit.roomIndex);
}
void sceneClosePortal(struct Scene* scene, int portalIndex) {

View file

@ -21,6 +21,7 @@ sk_definition_writer.add_definition("level", "struct LevelDefinition", "_geo", {
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),
portalSurfaceDynamicMappingRange = sk_definition_writer.reference_to(portal_surfaces.dynamic_mapping_range, 1),
portalSurfaceMappingIndices = sk_definition_writer.reference_to(portal_surfaces.portal_mapping_data, 1),
triggers = sk_definition_writer.reference_to(trigger.triggers, 1),
triggerCount = #trigger.triggers,

View file

@ -4,18 +4,19 @@ local animation = require('tools.level_scripts.animation')
local room_export = require('tools.level_scripts.room_export')
local dynamic_boxes = {}
local dynamic_boxes_original = {}
local function build_dynamic_box(box)
local parent_node_index = animation.get_bone_index_for_node(box.node)
if not parent_node_index then
return nil
return nil, nil
end
local parent_node = animation.get_bone_for_index(parent_node_index)
if not parent_node then
return nil
return nil, nil
end
local relative_transform = parent_node.full_transformation:inverse() * box.node.full_transformation
@ -31,14 +32,18 @@ local function build_dynamic_box(box)
rotation,
room_export.node_nearest_room_index(box.node),
parent_node_index - 1,
}, {
node = box.node,
parent_node_index = parent_node_index,
}
end
for _, box in pairs(sk_scene.nodes_for_type('@dynamic_box')) do
local dynamic_box = build_dynamic_box(box)
local dynamic_box, dynamic_box_original = build_dynamic_box(box)
if dynamic_box then
table.insert(dynamic_boxes, dynamic_box)
table.insert(dynamic_boxes_original, dynamic_box_original)
end
end
@ -47,4 +52,5 @@ sk_definition_writer.add_definition('dynamic_boxes', 'struct DynamicBoxDefinitio
return {
dynamic_boxes = dynamic_boxes,
dynamic_boxes_original = dynamic_boxes_original,
}

View file

@ -4,6 +4,7 @@ local sk_input = require('sk_input')
local sk_math = require('sk_math')
local sk_mesh = require('sk_mesh')
local sk_definition_writer = require('sk_definition_writer')
local dynamic_collision_export = require('tools.level_scripts.dynamic_collision_export')
local portal_surfaces = {}
@ -216,6 +217,7 @@ end
local portal_mapping_data = {}
local portal_mapping_range = {}
local dynamic_mapping_range = {}
local mapping_index = 0
@ -227,9 +229,13 @@ for _, quad in pairs(collision_export.colliders) do
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
if not surface.transform_index and is_coplanar_portal_surface(quad, surface.mesh, collision_with_padding) then
local portal_surface_index = static_to_portable_surface_mapping[static_index]
if portal_surface_index ~= -1 then
table.insert(portal_mapping_data, static_to_portable_surface_mapping[static_index])
mapping_index = mapping_index + 1
end
end
end
@ -240,11 +246,37 @@ for _, quad in pairs(collision_export.colliders) do
table.insert(portal_mapping_range, {start_mapping_index, mapping_index})
end
for _, box in pairs(dynamic_collision_export.dynamic_boxes_original) do
local start_mapping_index = mapping_index
for static_index, surface in pairs(static_export.static_nodes) do
-- simple hack for now. If collider and a portal surface share
-- the same transform then the portal surface is assumed to be
-- attached to the collider
if surface.transform_index == box.parent_node_index then
local portal_surface_index = static_to_portable_surface_mapping[static_index]
if portal_surface_index ~= -1 then
table.insert(portal_mapping_data, static_to_portable_surface_mapping[static_index])
mapping_index = mapping_index + 1
end
end
end
if mapping_index > 255 then
error("mapping_index was greater than 255")
end
table.insert(dynamic_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)
sk_definition_writer.add_definition("dynamic_collider_to_surface", "struct PortalSurfaceMappingRange[]", "_geo", dynamic_mapping_range)
return {
portal_surfaces = portal_surfaces,
portal_mapping_data = portal_mapping_data,
portal_mapping_range = portal_mapping_range,
dynamic_mapping_range = dynamic_mapping_range,
}