diff --git a/Dockerfile b/Dockerfile index 1fa8498..d737c04 100644 --- a/Dockerfile +++ b/Dockerfile @@ -40,7 +40,8 @@ RUN apt install -y binutils-mips-n64 \ cmake \ build-essential \ wget \ - unzip + unzip \ + sox COPY skelatool64/src skelatool64/src COPY skelatool64/main.cpp skelatool64/main.cpp @@ -62,6 +63,7 @@ RUN pip install vpk COPY Makefile Makefile COPY tools/export_fbx.py tools/export_fbx.py COPY tools/generate_level_list.js tools/generate_level_list.js +COPY tools/generate_sound_ids.js tools/generate_sound_ids.js COPY asm asm COPY assets assets COPY src src diff --git a/assets/test_chambers/test_chamber_00/test_chamber_00_0.blend b/assets/test_chambers/test_chamber_00/test_chamber_00_0.blend index e351d1f..a7b1e54 100644 Binary files a/assets/test_chambers/test_chamber_00/test_chamber_00_0.blend and b/assets/test_chambers/test_chamber_00/test_chamber_00_0.blend differ diff --git a/skelatool64/main.cpp b/skelatool64/main.cpp index 22dbb9c..75b9581 100644 --- a/skelatool64/main.cpp +++ b/skelatool64/main.cpp @@ -153,7 +153,7 @@ int main(int argc, char *argv[]) { roomGenerator.GenerateDefinitions(scene, fileDef); std::cout << "Generating collider definitions" << std::endl; - CollisionGenerator colliderGenerator(settings); + CollisionGenerator colliderGenerator(settings, roomGenerator.GetOutput()); colliderGenerator.TraverseScene(scene); colliderGenerator.GenerateDefinitions(scene, fileDef); diff --git a/skelatool64/src/definition_generator/CollisionGenerator.cpp b/skelatool64/src/definition_generator/CollisionGenerator.cpp index ffba371..fbb195d 100644 --- a/skelatool64/src/definition_generator/CollisionGenerator.cpp +++ b/skelatool64/src/definition_generator/CollisionGenerator.cpp @@ -4,9 +4,10 @@ #include -CollisionGenerator::CollisionGenerator(const DisplayListSettings& settings) : +CollisionGenerator::CollisionGenerator(const DisplayListSettings& settings, const RoomGeneratorOutput& roomOutput) : DefinitionGenerator(), - mSettings(settings) {} + mSettings(settings), + mRoomOutput(roomOutput) {} bool CollisionGenerator::ShouldIncludeNode(aiNode* node) { @@ -26,6 +27,8 @@ void CollisionGenerator::GenerateDefinitions(const aiScene* scene, CFileDefiniti std::string colliderTypesName = fileDefinition.GetUniqueName("collider_types"); std::string collisionObjectsName = fileDefinition.GetUniqueName("collision_objects"); + sortNodesByRoom(mIncludedNodes, mRoomOutput); + for (auto node = mIncludedNodes.begin(); node != mIncludedNodes.end(); ++node) { for (unsigned i = 0; i < (*node)->mNumMeshes; ++i) { aiMesh* mesh = scene->mMeshes[(*node)->mMeshes[i]]; diff --git a/skelatool64/src/definition_generator/CollisionGenerator.h b/skelatool64/src/definition_generator/CollisionGenerator.h index 020aadb..f498169 100644 --- a/skelatool64/src/definition_generator/CollisionGenerator.h +++ b/skelatool64/src/definition_generator/CollisionGenerator.h @@ -4,6 +4,7 @@ #include "DefinitionGenerator.h" #include "../DisplayListSettings.h" #include "CollisionQuad.h" +#include "RoomGenerator.h" struct CollisionGeneratorOutput { std::string quadsName; @@ -12,7 +13,7 @@ struct CollisionGeneratorOutput { class CollisionGenerator : public DefinitionGenerator { public: - CollisionGenerator(const DisplayListSettings& settings); + CollisionGenerator(const DisplayListSettings& settings, const RoomGeneratorOutput& roomOutput); virtual bool ShouldIncludeNode(aiNode* node); virtual void GenerateDefinitions(const aiScene* scene, CFileDefinition& fileDefinition); @@ -20,6 +21,7 @@ public: const CollisionGeneratorOutput& GetOutput() const; private: DisplayListSettings mSettings; + RoomGeneratorOutput mRoomOutput; CollisionGeneratorOutput mOutput; }; diff --git a/skelatool64/src/definition_generator/RoomGenerator.cpp b/skelatool64/src/definition_generator/RoomGenerator.cpp index 58b36c5..596c18b 100644 --- a/skelatool64/src/definition_generator/RoomGenerator.cpp +++ b/skelatool64/src/definition_generator/RoomGenerator.cpp @@ -20,19 +20,23 @@ RoomGenerator::RoomGenerator(const DisplayListSettings& settings): DefinitionGen short RoomGeneratorOutput::FindLocationRoom(const std::string& name) const { for (auto& location : namedLocations) { if (location.name == name) { - auto room = roomIndexMapping.find(location.node); - - if (room == roomIndexMapping.end()) { - return -1; - } - - return room->second; + return RoomForNode(location.node); } } return -1; } +int RoomGeneratorOutput::RoomForNode(const aiNode* node) const { + auto room = roomIndexMapping.find(node); + + if (room == roomIndexMapping.end()) { + return -1; + } + + return room->second; +} + struct RoomBlock { aiAABB boundingBox; int roomIndex; @@ -42,9 +46,9 @@ bool RoomGenerator::ShouldIncludeNode(aiNode* node) { return true; } -void sortNodesByRoom(std::vector& nodes, RoomGeneratorOutput& roomOutput) { +void sortNodesByRoom(std::vector& nodes, const RoomGeneratorOutput& roomOutput) { std::sort(nodes.begin(), nodes.end(), [&](const aiNode* a, const aiNode* b) -> bool { - return roomOutput.roomIndexMapping[a] < roomOutput.roomIndexMapping[b]; + return roomOutput.RoomForNode(a) < roomOutput.RoomForNode(b); }); } diff --git a/skelatool64/src/definition_generator/RoomGenerator.h b/skelatool64/src/definition_generator/RoomGenerator.h index 740e467..f4f929a 100644 --- a/skelatool64/src/definition_generator/RoomGenerator.h +++ b/skelatool64/src/definition_generator/RoomGenerator.h @@ -28,9 +28,10 @@ struct RoomGeneratorOutput { int roomCount; short FindLocationRoom(const std::string& name) const; + int RoomForNode(const aiNode* node) const; }; -void sortNodesByRoom(std::vector& nodes, RoomGeneratorOutput& roomOutput); +void sortNodesByRoom(std::vector& nodes, const RoomGeneratorOutput& roomOutput); class RoomGenerator : public DefinitionGenerator { public: diff --git a/skelatool64/src/definition_generator/TriggerGenerator.cpp b/skelatool64/src/definition_generator/TriggerGenerator.cpp index b849e90..3139902 100644 --- a/skelatool64/src/definition_generator/TriggerGenerator.cpp +++ b/skelatool64/src/definition_generator/TriggerGenerator.cpp @@ -20,14 +20,16 @@ CutsceneStep::CutsceneStep( bool doesBelongToCutscene(const CutsceneStep& startStep, const CutsceneStep& otherStep) { aiVector3D offset = otherStep.location - startStep.location; - aiVector3D relativeOffset = startStep.direction.Rotate(offset); + aiQuaternion directionCopy = startStep.direction; + aiVector3D relativeOffset = directionCopy.Rotate(offset); return relativeOffset.y >= 0.0f && relativeOffset.x * relativeOffset.x + relativeOffset.z * relativeOffset.z < 0.1f; } float distanceFromStart(const CutsceneStep& startStep, const CutsceneStep& otherStep) { aiVector3D offset = otherStep.location - startStep.location; - aiVector3D relativeOffset = startStep.direction.Rotate(offset); + aiQuaternion directionCopy = startStep.direction; + aiVector3D relativeOffset = directionCopy.Rotate(offset); return relativeOffset.y; } diff --git a/src/levels/levels.c b/src/levels/levels.c index a2ffd56..2d2a4dc 100644 --- a/src/levels/levels.c +++ b/src/levels/levels.c @@ -77,4 +77,42 @@ struct Location* levelGetLocation(short index) { } return &gCurrentLevel->locations[index]; +} + +int levelCheckDoorwaySides(struct Vector3* position, int currentRoom) { + struct Room* room = &gCurrentLevel->rooms[currentRoom]; + + int sideMask = 0; + + for (int i = 0; i < room->doorwayCount; ++i) { + if (planePointDistance(&gCurrentLevel->doorways[room->doorwayIndices[i]].quad.plane, position) > 0) { + sideMask |= 1 << 1; + } + } + + return sideMask; +} + +int levelCheckDoorwayCrossings(struct Vector3* position, int currentRoom, int sideMask) { + struct Room* room = &gCurrentLevel->rooms[currentRoom]; + + for (int i = 0; i < room->doorwayCount; ++i) { + struct Doorway* doorway = &gCurrentLevel->doorways[room->doorwayIndices[i]]; + + int prevSide = (sideMask & (1 << 1)) != 0; + int currSide = planePointDistance(&doorway->quad.plane, position) > 0; + + if (prevSide != currSide) { + struct Vector3 posOnFace; + planeProjectPoint(&doorway->quad.plane, position, &posOnFace); + + if (collisionQuadDetermineEdges(&posOnFace, &doorway->quad)) { + continue; + } + + return doorway->roomA == currentRoom ? doorway->roomB : doorway->roomA; + } + } + + return currentRoom; } \ No newline at end of file diff --git a/src/levels/levels.h b/src/levels/levels.h index 0e5d9f6..961ab5f 100644 --- a/src/levels/levels.h +++ b/src/levels/levels.h @@ -17,6 +17,10 @@ Gfx* levelMaterialRevert(int index); int levelQuadIndex(struct CollisionObject* pointer); +int levelCheckDoorwaySides(struct Vector3* position, int currentRoom); + +int levelCheckDoorwayCrossings(struct Vector3* position, int currentRoom, int sideMask); + void levelCheckTriggers(struct Vector3* playerPos); struct Location* levelGetLocation(short index); diff --git a/src/physics/collision_scene.h b/src/physics/collision_scene.h index 866e051..a0973d0 100644 --- a/src/physics/collision_scene.h +++ b/src/physics/collision_scene.h @@ -10,6 +10,17 @@ #define MAX_DYNAMIC_OBJECTS 16 +struct BroadphaseEdge { + float xValue; + short quadIndex; + short isStartEdge; +}; + +struct BroadphaseIndex { + struct BroadphaseEdge* edges; + short edgesCount; +}; + struct CollisionScene { struct CollisionObject* quads; struct Transform* portalTransforms[2]; diff --git a/src/player/player.c b/src/player/player.c index 6418be6..8ceb78d 100644 --- a/src/player/player.c +++ b/src/player/player.c @@ -8,6 +8,7 @@ #include "physics/collision_sphere.h" #include "physics/collision_scene.h" #include "physics/config.h" +#include "../levels/levels.h" #define GRAB_RAYCAST_DISTANCE 3.5f @@ -147,6 +148,8 @@ void playerUpdate(struct Player* player, struct Transform* cameraTransform) { struct Vector3 forward; struct Vector3 right; + int doorwayMask = levelCheckDoorwaySides(&player->body.transform.position, player->currentRoom); + struct Transform* transform = &player->body.transform; quatMultVector(&transform->rotation, &gForward, &forward); @@ -276,4 +279,6 @@ void playerUpdate(struct Player* player, struct Transform* cameraTransform) { cameraTransform->rotation = player->body.transform.rotation; transformPoint(transform, &gCameraOffset, &cameraTransform->position); playerUpdateGrabbedObject(player); + + player->currentRoom = levelCheckDoorwayCrossings(&player->body.transform.position, player->currentRoom, doorwayMask); }