mirror of
https://github.com/mwpenny/portal64-still-alive.git
synced 2024-10-20 10:37:37 -04:00
Get animatable colliders working
This commit is contained in:
parent
565e60584a
commit
26db9cf101
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -346,9 +372,30 @@ void sceneUpdate(struct Scene* scene) {
|
|||
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) {
|
||||
|
|
|
@ -34,6 +34,7 @@ struct Scene {
|
|||
struct Switch* switches;
|
||||
struct Vector3 freeCameraOffset;
|
||||
struct SceneAnimator animator;
|
||||
struct CollisionObject* dynamicColliders;
|
||||
OSTime cpuTime;
|
||||
OSTime lastFrameStart;
|
||||
OSTime lastFrameTime;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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,
|
||||
})
|
50
tools/level_scripts/dynamic_collision_export.lua
Normal file
50
tools/level_scripts/dynamic_collision_export.lua
Normal 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,
|
||||
}
|
Loading…
Reference in a new issue