Get animatable colliders working

This commit is contained in:
James Lambert 2023-01-03 22:12:25 -07:00
parent 565e60584a
commit 26db9cf101
8 changed files with 134 additions and 5 deletions

View file

@ -9,6 +9,7 @@
#include "../math/range.h"
#include "../sk64/skelatool_clip.h"
#include "../sk64/skelatool_armature.h"
#include "../physics/collision_box.h"
#define NO_TRANSFORM_INDEX 0xFF
@ -197,6 +198,14 @@ struct AnimationInfo {
short clipCount;
};
struct DynamicBoxDefinition {
struct CollisionBox box;
struct Vector3 position;
struct Quaternion rotation;
short roomIndex;
short transformIndex;
};
struct LevelDefinition {
struct CollisionObject* collisionQuads;
struct StaticContentElement *staticContent;
@ -221,6 +230,7 @@ struct LevelDefinition {
struct BoxDropperDefinition* boxDroppers;
struct AnimationInfo* animations;
struct SwitchDefinition* switches;
struct DynamicBoxDefinition* dynamicBoxes;
short collisionQuadCount;
short staticContentCount;
short portalSurfaceCount;
@ -238,6 +248,7 @@ struct LevelDefinition {
short boxDropperCount;
short animationInfoCount;
short switchCount;
short dynamicBoxCount;
short startLocation;
};

View file

@ -83,6 +83,7 @@ struct LevelDefinition* levelFixPointers(struct LevelDefinition* from, int point
result->signage = ADJUST_POINTER_POS(result->signage, pointerOffset);
result->boxDroppers = ADJUST_POINTER_POS(result->boxDroppers, pointerOffset);
result->switches = ADJUST_POINTER_POS(result->switches, pointerOffset);
result->dynamicBoxes = ADJUST_POINTER_POS(result->dynamicBoxes, pointerOffset);
result->animations = ADJUST_POINTER_POS(result->animations, pointerOffset);

View file

@ -38,6 +38,30 @@ Lights1 gSceneLights = gdSPDefLights1(128, 128, 128, 128, 128, 128, 0, 127, 0);
void sceneUpdateListeners(struct Scene* scene);
void sceneInitDynamicColliders(struct Scene* scene) {
int boxCount = gCurrentLevel->dynamicBoxCount;
struct CollisionObject* colliders = malloc(sizeof(struct CollisionObject) * boxCount);
struct ColliderTypeData* colliderType = malloc(sizeof(struct ColliderTypeData) * boxCount);
struct RigidBody* body = malloc(sizeof(struct RigidBody) * boxCount);
for (int i = 0; i < boxCount; ++i) {
colliderType[i].type = CollisionShapeTypeBox;
colliderType[i].data = &gCurrentLevel->dynamicBoxes[i].box;
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);
rigidBodyMarkKinematic(&body[i]);
body[i].currentRoom = gCurrentLevel->dynamicBoxes[i].roomIndex;
collisionSceneAddDynamicObject(&colliders[i]);
}
scene->dynamicColliders = colliders;
}
void sceneInit(struct Scene* scene) {
signalsInit(1);
@ -125,6 +149,8 @@ void sceneInit(struct Scene* scene) {
scene->freeCameraOffset = gZeroVec;
sceneInitDynamicColliders(scene);
sceneAnimatorInit(&scene->animator, gCurrentLevel->animations, gCurrentLevel->animationInfoCount);
}
@ -345,10 +371,31 @@ void sceneUpdate(struct Scene* scene) {
for (int i = 0; i < scene->boxDropperCount; ++i) {
boxDropperUpdate(&scene->boxDroppers[i]);
}
sceneAnimatorUpdate(&scene->animator);
for (int i = 0; i < gCurrentLevel->dynamicBoxCount; ++i) {
struct DynamicBoxDefinition* boxDef = &gCurrentLevel->dynamicBoxes[i];
struct Transform* baseTransform = sceneAnimatorTransformForIndex(&scene->animator, boxDef->transformIndex);
if (!baseTransform) {
continue;
}
struct Transform baseTransformUnscaled = *baseTransform;
vector3Scale(&baseTransformUnscaled.position, &baseTransformUnscaled.position, 1.0f / SCENE_SCALE);
struct Transform relativeTransform;
relativeTransform.position = boxDef->position;
relativeTransform.rotation = boxDef->rotation;
relativeTransform.scale = gOneVec;
transformConcat(&baseTransformUnscaled, &relativeTransform, &scene->dynamicColliders[i].body->transform);
collisionObjectUpdateBB(&scene->dynamicColliders[i]);
}
collisionSceneUpdateDynamics();
sceneAnimatorUpdate(&scene->animator);
levelCheckTriggers(&scene->player.lookTransform.position);
cutscenesUpdate();
@ -399,8 +446,7 @@ void sceneUpdate(struct Scene* scene) {
}
}
int sceneOpenPortal(struct Scene* scene, struct Transform* at, int portalIndex, int quadIndex, int roomIndex) {
struct PortalSurfaceMappingRange surfaceMapping = gCurrentLevel->portalSurfaceMappingRange[quadIndex];
int sceneOpenPortal(struct Scene* scene, struct Transform* at, int portalIndex, struct PortalSurfaceMappingRange surfaceMapping, struct CollisionObject* collisionObject, int roomIndex) {
for (int indexIndex = surfaceMapping.minPortalIndex; indexIndex < surfaceMapping.maxPortalIndex; ++indexIndex) {
int surfaceIndex = gCurrentLevel->portalSurfaceMappingIndices[indexIndex];
@ -423,7 +469,7 @@ int sceneOpenPortal(struct Scene* scene, struct Transform* at, int portalIndex,
portal->opacity = 0.0f;
}
contactSolverCheckPortalContacts(&gContactSolver, &gCurrentLevel->collisionQuads[quadIndex]);
contactSolverCheckPortalContacts(&gContactSolver, collisionObject);
return 1;
}
}
@ -468,7 +514,7 @@ int sceneFirePortal(struct Scene* scene, struct Ray* ray, struct Vector3* player
quatLook(&hitDirection, &upDir, &portalLocation.rotation);
}
return sceneOpenPortal(scene, &portalLocation, portalIndex, quadIndex, hit.roomIndex);
return sceneOpenPortal(scene, &portalLocation, portalIndex, gCurrentLevel->portalSurfaceMappingRange[quadIndex], &gCurrentLevel->collisionQuads[quadIndex], hit.roomIndex);
}
void sceneClosePortal(struct Scene* scene, int portalIndex) {

View file

@ -34,6 +34,7 @@ struct Scene {
struct Switch* switches;
struct Vector3 freeCameraOffset;
struct SceneAnimator animator;
struct CollisionObject* dynamicColliders;
OSTime cpuTime;
OSTime lastFrameStart;
OSTime lastFrameTime;

View file

@ -29,6 +29,21 @@ void sceneAnimatorUpdate(struct SceneAnimator* sceneAnimator) {
}
}
struct Transform* sceneAnimatorTransformForIndex(struct SceneAnimator* sceneAnimator, int index) {
if (index < 0) {
return NULL;
}
for (int i = 0; i < sceneAnimator->animatorCount; ++i) {
if (index < sceneAnimator->armatures[i].numberOfBones) {
return &sceneAnimator->armatures[i].pose[index];
}
index -= sceneAnimator->armatures[i].numberOfBones;
}
return NULL;
}
Mtx* sceneAnimatorBuildTransforms(struct SceneAnimator* sceneAnimator, struct RenderState* renderState) {
Mtx* result = renderStateRequestMatrices(renderState, sceneAnimator->boneCount);

View file

@ -21,6 +21,8 @@ void sceneAnimatorInit(struct SceneAnimator* sceneAnimator, struct AnimationInfo
void sceneAnimatorUpdate(struct SceneAnimator* sceneAnimator);
struct Transform* sceneAnimatorTransformForIndex(struct SceneAnimator* sceneAnimator, int index);
Mtx* sceneAnimatorBuildTransforms(struct SceneAnimator* sceneAnimator, struct RenderState* renderState);
void sceneAnimatorPlay(struct SceneAnimator* sceneAnimator, int animatorIndex, int animationIndex, float speed);

View file

@ -9,6 +9,7 @@ local world = require('tools.level_scripts.world')
local entities = require('tools.level_scripts.entities')
local signals = require('tools.level_scripts.signals')
local animation = require('tools.level_scripts.animation')
local dynamic_collision = require('tools.level_scripts.dynamic_collision_export')
sk_definition_writer.add_definition("level", "struct LevelDefinition", "_geo", {
collisionQuads = sk_definition_writer.reference_to(collision_export.collision_objects, 1),
@ -51,4 +52,6 @@ sk_definition_writer.add_definition("level", "struct LevelDefinition", "_geo", {
animationInfoCount = #animation.animated_nodes,
switches = sk_definition_writer.reference_to(entities.switches, 1),
switchCount = #entities.switches,
dynamicBoxes = sk_definition_writer.reference_to(dynamic_collision.dynamic_boxes, 1),
dynamicBoxCount = #dynamic_collision.dynamic_boxes,
})

View file

@ -0,0 +1,50 @@
local sk_definition_writer = require('sk_definition_writer')
local sk_scene = require('sk_scene')
local animation = require('tools.level_scripts.animation')
local room_export = require('tools.level_scripts.room_export')
local dynamic_boxes = {}
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
end
local parent_node = animation.get_bone_for_index(parent_node_index)
if not parent_node then
return nil
end
local relative_transform = parent_node.full_transformation:inverse() * box.node.full_transformation
local mesh_bb = box.node.meshes[1].bb
local _, rotation = relative_transform:decompose()
local pos = relative_transform * mesh_bb:lerp(0.5)
return {
{(mesh_bb.max - mesh_bb.min) * 0.5},
pos,
rotation,
room_export.node_nearest_room_index(box.node),
parent_node_index - 1,
}
end
for _, box in pairs(sk_scene.nodes_for_type('@dynamic_box')) do
local dynamic_box = build_dynamic_box(box)
if dynamic_box then
table.insert(dynamic_boxes, dynamic_box)
end
end
sk_definition_writer.add_definition('dynamic_boxes', 'struct DynamicBoxDefinition[]', '_geo', dynamic_boxes)
return {
dynamic_boxes = dynamic_boxes,
}