diff --git a/$ b/$ new file mode 100644 index 0000000..9af85d0 Binary files /dev/null and b/$ differ diff --git a/assets/materials/models/props/button.ims b/assets/materials/models/props/button.ims new file mode 100644 index 0000000..2ad007a --- /dev/null +++ b/assets/materials/models/props/button.ims @@ -0,0 +1 @@ +\( +clone -alpha off -crop 32x24+449+790 -fill "#c0b4a9" -draw 'rectangle 0,-1 32,0' -draw 'rectangle 0,23 32,32' -write portal_pak_modified/materials/models/props/button_base.png \) -composite -alpha off -crop 150x150+147+139 -resize 32x32 -fill "#6d1514" -draw 'rectangle 0,-1 14,0' -draw 'rectangle 17,-1 32,0' -draw 'rectangle 0,31 14,32' -draw 'rectangle 17,31 32,32' -draw 'rectangle -1,0 0,14' -draw 'rectangle -1,17 0,32' -draw 'rectangle 31,0 32,14' -draw 'rectangle 31,17 32,32' diff --git a/assets/materials/models/props/button_half.ims.off b/assets/materials/models/props/button_half.ims.off new file mode 100644 index 0000000..c369365 --- /dev/null +++ b/assets/materials/models/props/button_half.ims.off @@ -0,0 +1 @@ +-alpha off \( +clone -crop 150x150+147+139 -rotate 180 -alpha on -channel a -evaluate set 50% +repage \) -geometry +147+139 -composite \( +clone -crop 150x150+147+139 -rotate 90 -alpha on -channel a -evaluate set 50% +repage \) -geometry +147+139 -composite \ No newline at end of file diff --git a/assets/materials/objects.skm.yaml b/assets/materials/objects.skm.yaml index 2acef2f..e2d99a1 100644 --- a/assets/materials/objects.skm.yaml +++ b/assets/materials/objects.skm.yaml @@ -18,4 +18,48 @@ materials: set: [G_LIGHTING, G_SHADE] gDPSetCombineMode: color: ["PRIMITIVE", "0", "SHADE", "0"] + + button_base: + gDPSetTile: + - null + - filename: ../../portal_pak_modified/materials/models/props/button_base.png + fmt: G_IM_FMT_RGBA + siz: G_IM_SIZ_16b + tmem: 256 + s: + wrap: false + t: + wrap: false + gSPTexture: + tile: 1 + gSPGeometryMode: + set: [G_LIGHTING, G_SHADE] + gDPSetCombineMode: + color: ["SHADE", "0", "TEXEL0", "0"] + + button_base_black: + gDPSetPrimColor: + r: 32 + g: 32 + b: 32 + gSPGeometryMode: + set: [G_LIGHTING, G_SHADE] + gDPSetCombineMode: + color: ["PRIMITIVE", "0", "SHADE", "0"] + + button_top: + gDPSetTile: + filename: ../../portal_pak_modified/materials/models/props/button.png + fmt: G_IM_FMT_RGBA + siz: G_IM_SIZ_16b + s: + wrap: false + t: + wrap: false + gSPTexture: + tile: 0 + gSPGeometryMode: + set: [G_LIGHTING, G_SHADE] + gDPSetCombineMode: + color: ["SHADE", "0", "TEXEL0", "0"] \ No newline at end of file diff --git a/assets/materials/sprites/hud/portal_crosshairs_mask.png b/assets/materials/sprites/hud/portal_crosshairs_mask.png deleted file mode 100644 index 47a1268..0000000 Binary files a/assets/materials/sprites/hud/portal_crosshairs_mask.png and /dev/null differ diff --git a/assets/materials/static.skm.yaml b/assets/materials/static.skm.yaml index a811ce5..252ba6d 100644 --- a/assets/materials/static.skm.yaml +++ b/assets/materials/static.skm.yaml @@ -103,4 +103,37 @@ materials: gSPGeometryMode: set: [G_LIGHTING, G_SHADE] gDPSetCombineMode: - color: ["SHADE", "0", "PRIMITIVE", "0"] \ No newline at end of file + color: ["SHADE", "0", "PRIMITIVE", "0"] + + plastic/plasticwall001a: + gDPSetPrimColor: + r: 230 + g: 230 + b: 230 + gSPGeometryMode: + set: [G_LIGHTING, G_SHADE] + gDPSetCombineMode: + color: ["SHADE", "0", "PRIMITIVE", "0"] + + button: + gDPSetTile: + - filename: ../../portal_pak_modified/materials/models/props/button.png + fmt: G_IM_FMT_RGBA + siz: G_IM_SIZ_16b + s: + wrap: false + t: + wrap: false + - filename: ../../portal_pak_modified/materials/models/props/button_base.png + fmt: G_IM_FMT_RGBA + siz: G_IM_SIZ_16b + tmem: 256 + s: + wrap: false + t: + wrap: false + + gSPGeometryMode: + set: [G_LIGHTING, G_SHADE] + gDPSetCombineMode: + color: ["SHADE", "0", "TEXEL0", "0"] diff --git a/assets/models/props/button.blend b/assets/models/props/button.blend new file mode 100644 index 0000000..f061b6d Binary files /dev/null and b/assets/models/props/button.blend differ diff --git a/assets/models/props/button.flags b/assets/models/props/button.flags new file mode 100644 index 0000000..6c107fa --- /dev/null +++ b/assets/models/props/button.flags @@ -0,0 +1 @@ +-m assets/materials/static.skm.yaml -m assets/materials/objects.skm.yaml -D button \ No newline at end of file diff --git a/assets/sound/weapons/portalgun/portal_open2.sox b/assets/sound/weapons/portalgun/portal_open2.sox new file mode 100644 index 0000000..86f4847 --- /dev/null +++ b/assets/sound/weapons/portalgun/portal_open2.sox @@ -0,0 +1 @@ +-c 1 \ No newline at end of file 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 4dce9fa..fcef9c5 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 75b9581..0090cf2 100644 --- a/skelatool64/main.cpp +++ b/skelatool64/main.cpp @@ -162,7 +162,7 @@ int main(int argc, char *argv[]) { staticGenerator.TraverseScene(scene); staticGenerator.GenerateDefinitions(scene, fileDef); - TriggerGenerator triggerGenerator(settings); + TriggerGenerator triggerGenerator(settings, roomGenerator.GetOutput()); triggerGenerator.TraverseScene(scene); triggerGenerator.GenerateDefinitions(scene, fileDef); diff --git a/skelatool64/schema/material-schema.json b/skelatool64/schema/material-schema.json index c622b64..5c3b4a0 100755 --- a/skelatool64/schema/material-schema.json +++ b/skelatool64/schema/material-schema.json @@ -356,12 +356,6 @@ "type": "number", "minimum": 0, "maximum": 7 - }, - "s": { - "$ref": "#/definitions/textureCoordinateSettings" - }, - "t": { - "$ref": "#/definitions/textureCoordinateSettings" } } }, @@ -403,6 +397,12 @@ "minimum": 0, "maximum": 15 }, + "s": { + "$ref": "#/definitions/textureCoordinateSettings" + }, + "t": { + "$ref": "#/definitions/textureCoordinateSettings" + }, "twoTone": { "type": "boolean" } diff --git a/skelatool64/src/MeshWriter.cpp b/skelatool64/src/MeshWriter.cpp index af53efa..4015588 100644 --- a/skelatool64/src/MeshWriter.cpp +++ b/skelatool64/src/MeshWriter.cpp @@ -9,6 +9,16 @@ MaterialCollector::MaterialCollector(): mSceneCount(0) {} +void useTexture(std::set>& usedTextures, std::shared_ptr texture, CFileDefinition& fileDefinition, const std::string& fileSuffix) { + if (usedTextures.find(texture) != usedTextures.end()) { + return; + } + + usedTextures.insert(texture); + + fileDefinition.AddDefinition(std::move(texture->GenerateDefinition(fileDefinition.GetUniqueName(texture->Name()), fileSuffix))); +} + void MaterialCollector::UseMaterial(const std::string& material, DisplayListSettings& settings) { auto materialDL = settings.mMaterials.find(material); @@ -20,13 +30,6 @@ void MaterialCollector::UseMaterial(const std::string& material, DisplayListSett if (prevCount == mMaterialUseCount.end()) { mMaterialUseCount[material] = 1; - - for (int i = 0; i < MAX_TILE_COUNT; ++i) { - auto tile = &materialDL->second->mState.tiles[i]; - if (tile->isOn && tile->texture) { - mUsedTextures.insert(tile->texture); - } - } } else { mMaterialUseCount[material] = prevCount->second + 1; } @@ -40,14 +43,19 @@ void MaterialCollector::CollectMaterialResources(const aiScene* scene, std::vect } void MaterialCollector::GenerateMaterials(DisplayListSettings& settings, CFileDefinition& fileDefinition, const std::string& fileSuffix) { - for (auto image : mUsedTextures) { - fileDefinition.AddDefinition(std::move(image->GenerateDefinition(fileDefinition.GetUniqueName(image->Name()), fileSuffix))); - } - for (auto useCount = mMaterialUseCount.begin(); useCount != mMaterialUseCount.end(); ++useCount) { if (useCount->second > 1 || mSceneCount > 1) { + auto material = settings.mMaterials.find(useCount->first); + + for (int i = 0; i < MAX_TILE_COUNT; ++i) { + auto tile = &material->second->mState.tiles[i]; + if (tile->isOn && tile->texture && !settings.mDefaultMaterialState.IsTextureLoaded(tile->texture, tile->tmem)) { + useTexture(mUsedTextures, tile->texture, fileDefinition, fileSuffix); + } + } + DisplayList materialDL(fileDefinition.GetUniqueName(useCount->first)); - settings.mMaterials.find(useCount->first)->second->Write(fileDefinition, settings.mDefaultMaterialState, materialDL.GetDataChunk()); + material->second->Write(fileDefinition, settings.mDefaultMaterialState, materialDL.GetDataChunk()); mMaterialNameMapping[useCount->first] = materialDL.GetName(); auto dl = materialDL.Generate(fileSuffix); @@ -59,6 +67,8 @@ void MaterialCollector::GenerateMaterials(DisplayListSettings& settings, CFileDe void generateMeshIntoDLWithMaterials(const aiScene* scene, CFileDefinition& fileDefinition, MaterialCollector* materials, std::vector& renderChunks, DisplayListSettings& settings, DisplayList &displayList, const std::string& modelSuffix) { RCPState rcpState(settings.mDefaultMaterialState, settings.mVertexCacheSize, settings.mMaxMatrixDepth, settings.mCanPopMultipleMatrices); + std::set> usedTextures; + for (auto chunk = renderChunks.begin(); chunk != renderChunks.end(); ++chunk) { if (materials) { std::string materialName = ExtendedMesh::GetMaterialName(scene->mMaterials[chunk->mMesh->mMesh->mMaterialIndex]); @@ -71,7 +81,17 @@ void generateMeshIntoDLWithMaterials(const aiScene* scene, CFileDefinition& file auto material = settings.mMaterials.find(materialName); if (material != settings.mMaterials.end()) { - material->second->Write(fileDefinition, rcpState.GetMaterialState(), displayList.GetDataChunk()); + auto& materialState = rcpState.GetMaterialState(); + + for (int i = 0; i < MAX_TILE_COUNT; ++i) { + auto tile = &material->second->mState.tiles[i]; + if (tile->isOn && tile->texture && !materialState.IsTextureLoaded(tile->texture, tile->tmem)) { + useTexture(usedTextures, tile->texture, fileDefinition, modelSuffix); + } + } + + material->second->Write(fileDefinition, materialState, displayList.GetDataChunk()); + applyMaterial(material->second->mState, materialState); } } @@ -94,7 +114,6 @@ void generateMeshIntoDLWithMaterials(const aiScene* scene, CFileDefinition& file void generateMeshIntoDL(const aiScene* scene, CFileDefinition& fileDefinition, std::vector& renderChunks, DisplayListSettings& settings, DisplayList &displayList, const std::string& fileSuffix) { MaterialCollector materials; - materials.CollectMaterialResources(scene, renderChunks, settings); materials.GenerateMaterials(settings, fileDefinition, fileSuffix); generateMeshIntoDLWithMaterials(scene, fileDefinition, &materials, renderChunks, settings, displayList, fileSuffix); diff --git a/skelatool64/src/MeshWriter.h b/skelatool64/src/MeshWriter.h index bde8c02..fa0b3e7 100644 --- a/skelatool64/src/MeshWriter.h +++ b/skelatool64/src/MeshWriter.h @@ -24,6 +24,8 @@ public: std::map mMaterialUseCount; std::map mMaterialNameMapping; std::map mResourceNameMapping; + +private: }; void generateMeshIntoDLWithMaterials(const aiScene* scene, CFileDefinition& fileDefinition, MaterialCollector* materials, std::vector& renderChunks, DisplayListSettings& settings, DisplayList &displayList, const std::string& modelSuffix); diff --git a/skelatool64/src/definition_generator/RoomGenerator.cpp b/skelatool64/src/definition_generator/RoomGenerator.cpp index 56c63f3..498ec45 100644 --- a/skelatool64/src/definition_generator/RoomGenerator.cpp +++ b/skelatool64/src/definition_generator/RoomGenerator.cpp @@ -27,6 +27,16 @@ short RoomGeneratorOutput::FindLocationRoom(const std::string& name) const { return -1; } +short RoomGeneratorOutput::FindLocationIndex(const std::string& name) const { + for (auto& location : namedLocations) { + if (location.name == name) { + return location.index; + } + } + + return -1; +} + int RoomGeneratorOutput::RoomForNode(const aiNode* node) const { auto room = roomIndexMapping.find(node); diff --git a/skelatool64/src/definition_generator/RoomGenerator.h b/skelatool64/src/definition_generator/RoomGenerator.h index f4f929a..2c689d2 100644 --- a/skelatool64/src/definition_generator/RoomGenerator.h +++ b/skelatool64/src/definition_generator/RoomGenerator.h @@ -28,6 +28,7 @@ struct RoomGeneratorOutput { int roomCount; short FindLocationRoom(const std::string& name) const; + short FindLocationIndex(const std::string& name) const; int RoomForNode(const aiNode* node) const; }; diff --git a/skelatool64/src/definition_generator/TriggerGenerator.cpp b/skelatool64/src/definition_generator/TriggerGenerator.cpp index 3139902..8041902 100644 --- a/skelatool64/src/definition_generator/TriggerGenerator.cpp +++ b/skelatool64/src/definition_generator/TriggerGenerator.cpp @@ -33,13 +33,13 @@ float distanceFromStart(const CutsceneStep& startStep, const CutsceneStep& other return relativeOffset.y; } -TriggerGenerator::TriggerGenerator(const DisplayListSettings& settings): DefinitionGenerator(), mSettings(settings) {} +TriggerGenerator::TriggerGenerator(const DisplayListSettings& settings, const RoomGeneratorOutput& roomOutput): DefinitionGenerator(), mSettings(settings), mRoomOutput(roomOutput) {} bool TriggerGenerator::ShouldIncludeNode(aiNode* node) { return (StartsWith(node->mName.C_Str(), TRIGGER_PREFIX) && node->mNumMeshes >= 1) || StartsWith(node->mName.C_Str(), CUTSCENE_PREFIX); } -std::unique_ptr generateCutsceneStep(CutsceneStep& step) { +std::unique_ptr TriggerGenerator::GenerateCutsceneStep(CutsceneStep& step) { std::unique_ptr result(new StructureDataChunk()); if ((step.command == "play_sound" || step.command == "start_sound") && step.args.size() >= 1) { @@ -66,6 +66,17 @@ std::unique_ptr generateCutsceneStep(CutsceneStep& step) { result->AddPrimitive("CutsceneStepTypeDelay"); result->AddPrimitive("delay", std::atof(step.args[0].c_str())); return result; + } else if (step.command == "open_portal" && step.args.size() >= 1) { + short roomLocation = mRoomOutput.FindLocationIndex(step.args[0]); + + if (roomLocation != -1) { + result->AddPrimitive("CutsceneStepTypeOpenPortal"); + std::unique_ptr openPortal(new StructureDataChunk()); + openPortal->AddPrimitive(roomLocation); + openPortal->AddPrimitive((step.args.size() >= 2 && step.args[1] == "1") ? 1 : 0); + result->Add("openPortal", std::move(openPortal)); + return result; + } } result->AddPrimitive("CutsceneStepTypeNoop"); @@ -131,7 +142,7 @@ void TriggerGenerator::GenerateCutscenes(std::map steps(new StructureDataChunk()); for (auto& step : cutscene.steps) { - steps->Add(std::move(generateCutsceneStep(*step))); + steps->Add(std::move(GenerateCutsceneStep(*step))); } std::string stepsName = fileDefinition.GetUniqueName(cutscene.name + "_steps"); diff --git a/skelatool64/src/definition_generator/TriggerGenerator.h b/skelatool64/src/definition_generator/TriggerGenerator.h index 39f4fc3..8d8d556 100644 --- a/skelatool64/src/definition_generator/TriggerGenerator.h +++ b/skelatool64/src/definition_generator/TriggerGenerator.h @@ -3,6 +3,7 @@ #include "DefinitionGenerator.h" #include "../DisplayListSettings.h" +#include "RoomGenerator.h" #include struct Trigger { @@ -32,7 +33,7 @@ struct Cutscene { class TriggerGenerator : public DefinitionGenerator { public: - TriggerGenerator(const DisplayListSettings& settings); + TriggerGenerator(const DisplayListSettings& settings, const RoomGeneratorOutput& roomOutput); virtual bool ShouldIncludeNode(aiNode* node); virtual void GenerateDefinitions(const aiScene* scene, CFileDefinition& fileDefinition); @@ -41,8 +42,10 @@ public: private: DisplayListSettings mSettings; TriggerGeneratorOutput mOutput; + RoomGeneratorOutput mRoomOutput; void GenerateCutscenes(std::map>& output, CFileDefinition& fileDefinition); + std::unique_ptr GenerateCutsceneStep(CutsceneStep& step); }; #endif \ No newline at end of file diff --git a/skelatool64/src/materials/MaterialParser.cpp b/skelatool64/src/materials/MaterialParser.cpp index 053bfc1..7d83826 100644 --- a/skelatool64/src/materials/MaterialParser.cpp +++ b/skelatool64/src/materials/MaterialParser.cpp @@ -649,6 +649,7 @@ void parseTiles(const YAML::Node& node, MaterialState& state, ParseResult& outpu state.textureState.isOn = true; } } + return; } output.mErrors.push_back(ParseError(formatError("Expected a tile or array of tiles", node.Mark()))); diff --git a/skelatool64/src/materials/MaterialState.cpp b/skelatool64/src/materials/MaterialState.cpp index fabc7ab..c410a89 100644 --- a/skelatool64/src/materials/MaterialState.cpp +++ b/skelatool64/src/materials/MaterialState.cpp @@ -38,6 +38,11 @@ struct FlagList FlagList::GetDeltaFrom(struct FlagList& other) { return result; } +void FlagList::ApplyFrom(const FlagList& other) { + knownFlags |= other.knownFlags; + flags = (other.flags & other.knownFlags) | (flags & ~other.knownFlags); +} + TextureCoordinateState::TextureCoordinateState(): wrap(true), mirror(false), @@ -209,6 +214,17 @@ MaterialState::MaterialState() : useBlendColor(false) {} + +bool MaterialState::IsTextureLoaded(std::shared_ptr texture, int tmem) const { + for (int i = 0; i < MAX_TILE_COUNT; ++i) { + if (tiles[i].texture == texture && tiles[i].tmem == tmem) { + return true; + } + } + + return false; +} + void appendToFlags(std::ostringstream& flags, const std::string& value) { if (flags.tellp() != 0) { flags << " | "; @@ -568,4 +584,109 @@ void generateMaterial(CFileDefinition& fileDef, const MaterialState& from, const } // TODO fill color -} \ No newline at end of file +} + +void applyMaterial(const MaterialState& from, MaterialState& to) { + for (int i = 0; i < MAX_TILE_COUNT; ++i) { + if (from.tiles[i].isOn) { + to.tiles[i] = from.tiles[i]; + } + } + + if (from.textureState.isOn) { + to.textureState = from.textureState; + } + + to.geometryModes.ApplyFrom(from.geometryModes); + + if (from.pipelineMode != PipelineMode::Unknown) { + to.pipelineMode = from.pipelineMode; + } + + if (from.cycleType != CycleType::Unknown) { + to.cycleType = from.cycleType; + } + + if (from.perspectiveMode != PerspectiveMode::Unknown) { + to.perspectiveMode = from.perspectiveMode; + } + + if (from.textureDetail != TextureDetail::Unknown) { + to.textureDetail = from.textureDetail; + } + + if (from.textureLOD != TextureLOD::Unknown) { + to.textureLOD = from.textureLOD; + } + + if (from.textureLUT != TextureLUT::Unknown) { + to.textureLUT = from.textureLUT; + } + + if (from.textureFilter != TextureFilter::Unknown) { + to.textureFilter = from.textureFilter; + } + + if (from.textureConvert != TextureConvert::Unknown) { + to.textureConvert = from.textureConvert; + } + + if (from.combineKey != CombineKey::Unknown) { + to.combineKey = from.combineKey; + } + + if (from.colorDither != ColorDither::Unknown) { + to.colorDither = from.colorDither; + } + + if (from.alphaDither != AlphaDither::Unknown) { + to.alphaDither = from.alphaDither; + } + + if (from.alphaCompare != AlphaCompare::Unknown) { + to.alphaCompare = from.alphaCompare; + } + + if (from.depthSource != DepthSource::Unknown) { + to.depthSource = from.depthSource; + } + + if (from.hasCombineMode) { + to.hasCombineMode = true; + to.cycle1Combine = from.cycle1Combine; + to.cycle2Combine = from.cycle2Combine; + } + + if (from.hasRenderMode) { + to.hasRenderMode = true; + to.cycle1RenderMode = from.cycle1RenderMode; + to.cycle2RenderMode = from.cycle2RenderMode; + } + + if (from.usePrimitiveColor) { + to.usePrimitiveColor = true; + to.primitiveColor = from.primitiveColor; + to.primitiveM = from.primitiveM; + to.primitiveL = from.primitiveL; + } + + if (from.useEnvColor) { + to.useEnvColor = true; + to.envColor = from.envColor; + } + + if (from.useFillColor) { + to.useFillColor = true; + to.fillColor = from.fillColor; + } + + if (from.useFogColor) { + to.useFogColor = true; + to.fogColor = from.fogColor; + } + + if (from.useBlendColor) { + to.useBlendColor = true; + to.blendColor = from.blendColor; + } +} \ No newline at end of file diff --git a/skelatool64/src/materials/MaterialState.h b/skelatool64/src/materials/MaterialState.h index b336092..a9350d8 100644 --- a/skelatool64/src/materials/MaterialState.h +++ b/skelatool64/src/materials/MaterialState.h @@ -15,6 +15,8 @@ struct FlagList { void DeleteFlag(int mask); struct FlagList GetDeltaFrom(struct FlagList& other); + + void ApplyFrom(const FlagList& other); }; struct TextureCoordinateState { @@ -139,8 +141,12 @@ public: bool useBlendColor; PixelRGBAu8 blendColor; + + bool IsTextureLoaded(std::shared_ptr texture, int tmem) const; }; void generateMaterial(CFileDefinition& fileDef, const MaterialState& from, const MaterialState& to, StructureDataChunk& output); +void applyMaterial(const MaterialState& from, MaterialState& to); + #endif \ No newline at end of file diff --git a/src/audio/clips.c b/src/audio/clips.c index 882032d..b2cd68d 100644 --- a/src/audio/clips.c +++ b/src/audio/clips.c @@ -3,4 +3,5 @@ #include "../../build/src/audio/clips.h" -unsigned short soundsPortalEnter = SOUNDS_PORTAL_ENTER1; \ No newline at end of file +unsigned short soundsPortalEnter = SOUNDS_PORTAL_ENTER1; +unsigned short soundsPortalOpen2 = SOUNDS_PORTAL_OPEN2; \ No newline at end of file diff --git a/src/audio/clips.h b/src/audio/clips.h index aaea0e3..07e9e5b 100644 --- a/src/audio/clips.h +++ b/src/audio/clips.h @@ -3,4 +3,6 @@ extern unsigned short soundsPortalEnter; +extern unsigned short soundsPortalOpen2; + #endif \ No newline at end of file diff --git a/src/levels/cutscene_runner.c b/src/levels/cutscene_runner.c index a3a7be2..61b6829 100644 --- a/src/levels/cutscene_runner.c +++ b/src/levels/cutscene_runner.c @@ -1,6 +1,8 @@ #include "cutscene_runner.h" #include "../audio/soundplayer.h" #include "../util/time.h" +#include "../scene/scene.h" +#include "../levels/levels.h" struct CutsceneRunner gCutsceneRunner; @@ -18,6 +20,16 @@ void cutsceneRunnerStartStep(struct CutsceneRunner* runner) { case CutsceneStepTypeDelay: runner->state.delay = step->delay; break; + case CutsceneStepTypeOpenPortal: + { + struct Location* location = &gCurrentLevel->locations[step->openPortal.locationIndex]; + struct Ray firingRay; + firingRay.origin = location->transform.position; + quatMultVector(&location->transform.rotation, &gForward, &firingRay.dir); + vector3AddScaled(&location->transform.position, &firingRay.dir, -0.1f, &firingRay.origin); + sceneFirePortal(&gScene, &firingRay, &gUp, step->openPortal.portalIndex, location->roomIndex); + break; + } default: } } diff --git a/src/levels/level_definition.h b/src/levels/level_definition.h index 09696c7..7fadcf8 100644 --- a/src/levels/level_definition.h +++ b/src/levels/level_definition.h @@ -26,6 +26,7 @@ enum CutsceneStepType { CutsceneStepTypePlaySound, CutsceneStepTypeStartSound, CutsceneStepTypeDelay, + CutsceneStepTypeOpenPortal, }; struct CutsceneStep { @@ -37,6 +38,10 @@ struct CutsceneStep { u8 volume; u8 pitch; } playSound; + struct { + u16 locationIndex; + u16 portalIndex; + } openPortal; float delay; int noop; }; diff --git a/src/main.c b/src/main.c index 27dc3b4..bee3be1 100644 --- a/src/main.c +++ b/src/main.c @@ -84,7 +84,7 @@ static void initProc(void* arg) { for(;;); } -static struct Scene gScene; +struct Scene gScene; extern OSMesgQueue dmaMessageQ; @@ -128,6 +128,7 @@ static void gameProc(void* arg) { u32 pendingGFX = 0; u32 drawBufferIndex = 0; u8 frameControl = 0; + u8 inputIgnore = 6; u16* memoryEnd = graphicsLayoutScreenBuffers((u16*)PHYS_TO_K0(osMemSize)); @@ -174,7 +175,11 @@ static void gameProc(void* arg) { } controllersTriggerRead(); - sceneUpdate(&gScene); + if (inputIgnore) { + --inputIgnore; + } else { + sceneUpdate(&gScene); + } timeUpdateDelta(); soundPlayerUpdate(); diff --git a/src/physics/collision_scene.c b/src/physics/collision_scene.c index 3340d19..475aba2 100644 --- a/src/physics/collision_scene.c +++ b/src/physics/collision_scene.c @@ -203,7 +203,7 @@ void collisionSceneRaycastRoom(struct CollisionScene* scene, struct Room* room, for (int i = range->min; i < range->max; ++i) { struct RaycastHit hitTest; - if (raycastQuad(&scene->quads[room->quadIndices[i]], ray, hit->distance, &hitTest) && hitTest.distance < hit->distance) { + if (raycastQuad(&scene->quads[room->quadIndices[i]], ray, hit->distance, &hitTest) && hitTest.distance < hit->distance && vector3Dot(&hitTest.normal, &ray->dir) < 0.0f) { hit->at = hitTest.at; hit->normal = hitTest.normal; hit->distance = hitTest.distance; diff --git a/src/scene/hud.c b/src/scene/hud.c index dc7d89e..287e87a 100644 --- a/src/scene/hud.c +++ b/src/scene/hud.c @@ -24,19 +24,19 @@ void hudRender(struct RenderState* renderState) { gSPDisplayList(renderState->dl++, hud_material_list[PORTAL_CROSSHAIRS_INDEX]); - gSPTextureRectangle(renderState->dl++, - (SCREEN_WD - HUD_CENTER_WIDTH) << 1, (SCREEN_HT - HUD_CENTER_HEIGHT) << 1, - (SCREEN_WD + HUD_CENTER_WIDTH) << 1, (SCREEN_HT + HUD_CENTER_HEIGHT) << 1, - G_TX_RENDERTILE, HUD_CENTER_S << 5, HUD_CENTER_T << 5, 1 << 10, 1 << 10); + // gSPTextureRectangle(renderState->dl++, + // (SCREEN_WD - HUD_CENTER_WIDTH) << 1, (SCREEN_HT - HUD_CENTER_HEIGHT) << 1, + // (SCREEN_WD + HUD_CENTER_WIDTH) << 1, (SCREEN_HT + HUD_CENTER_HEIGHT) << 1, + // G_TX_RENDERTILE, HUD_CENTER_S << 5, HUD_CENTER_T << 5, 1 << 10, 1 << 10); - gDPSetPrimColor(renderState->dl++, 255, 255, 255, 128, 0, 255); + gDPSetPrimColor(renderState->dl++, 255, 255, 0, 128, 255, 255); gSPTextureRectangle(renderState->dl++, HUD_UPPER_X, HUD_UPPER_Y, HUD_UPPER_X + (HUD_OUTER_WIDTH << 2), HUD_UPPER_Y + (HUD_OUTER_HEIGHT << 2), G_TX_RENDERTILE, 0 << 5, 0 << 5, 1 << 10, 1 << 10); - gDPSetPrimColor(renderState->dl++, 255, 255, 0, 128, 255, 255); + gDPSetPrimColor(renderState->dl++, 255, 255, 255, 128, 0, 255); gSPTextureRectangle(renderState->dl++, HUD_LOWER_X, HUD_LOWER_Y, diff --git a/src/scene/portal.c b/src/scene/portal.c index c54420e..8a6361a 100644 --- a/src/scene/portal.c +++ b/src/scene/portal.c @@ -68,7 +68,7 @@ void renderPropsInit(struct RenderProps* props, struct Camera* camera, float asp props->maxY = SCREEN_HT; } -#define MIN_VP_WIDTH 42 +#define MIN_VP_WIDTH 64 void renderPropscheckViewportSize(int* min, int* max, int screenSize) { if (*max < MIN_VP_WIDTH) { @@ -197,7 +197,7 @@ void portalRender(struct Portal* portal, struct Portal* otherPortal, struct Rend transformToMatrix(&finalTransform, portalTransform, SCENE_SCALE); - if (props->currentDepth == 0) { + if (props->currentDepth == 0 || !otherPortal) { Mtx* matrix = renderStateRequestMatrices(renderState, 1); guMtxF2L(portalTransform, matrix); diff --git a/src/scene/scene.c b/src/scene/scene.c index a6f0c99..608fe14 100644 --- a/src/scene/scene.c +++ b/src/scene/scene.c @@ -38,19 +38,6 @@ void sceneInit(struct Scene* scene) { portalInit(&scene->portals[0], 0); portalInit(&scene->portals[1], PortalFlagsOddParity); - gCollisionScene.portalTransforms[0] = &scene->portals[0].transform; - gCollisionScene.portalTransforms[1] = &scene->portals[1].transform; - - scene->portals[0].transform.position.x = 3.75f; - scene->portals[0].transform.position.y = 1.5f; - scene->portals[0].transform.position.z = -4.5f; - - scene->portals[1].transform.position.x = 0.0f; - scene->portals[1].transform.position.y = 1.0f; - scene->portals[1].transform.position.z = -6.0f; - - - quatAxisAngle(&gUp, M_PI * 0.5f, &scene->portals[1].transform.rotation); for (int i = 0; i < MAX_CUBES; ++i) { cubeInit(&scene->cubes[i]); @@ -72,12 +59,24 @@ void sceneRenderWithProperties(void* data, struct RenderProps* properties, struc staticRenderDetermineVisibleRooms(&properties->cullingInfo, properties->fromRoom, &visibleRooms); int closerPortal = vector3DistSqrd(&properties->camera.transform.position, &scene->portals[0].transform.position) > vector3DistSqrd(&properties->camera.transform.position, &scene->portals[1].transform.position) ? 0 : 1; + int otherPortal = 1 - closerPortal; - if (properties->fromPortalIndex != closerPortal && staticRenderIsRoomVisible(visibleRooms, gCollisionScene.portalRooms[closerPortal])) { - portalRender(&scene->portals[closerPortal], &scene->portals[1 - closerPortal], properties, sceneRenderWithProperties, data, renderState); - } - if (properties->fromPortalIndex != 1 - closerPortal && staticRenderIsRoomVisible(visibleRooms, gCollisionScene.portalRooms[1 - closerPortal])) { - portalRender(&scene->portals[1 - closerPortal], &scene->portals[closerPortal], properties, sceneRenderWithProperties, data, renderState); + for (int i = 0; i < 2; ++i) { + if (gCollisionScene.portalTransforms[closerPortal] && + properties->fromPortalIndex != closerPortal && + staticRenderIsRoomVisible(visibleRooms, gCollisionScene.portalRooms[closerPortal])) { + portalRender( + &scene->portals[closerPortal], + gCollisionScene.portalTransforms[otherPortal] ? &scene->portals[otherPortal] : NULL, + properties, + sceneRenderWithProperties, + data, + renderState + ); + } + + closerPortal = 1 - closerPortal; + otherPortal = 1 - otherPortal; } staticRender(&properties->cullingInfo, visibleRooms, renderState); @@ -135,7 +134,7 @@ void sceneRender(struct Scene* scene, struct RenderState* renderState, struct Gr hudRender(renderState); - sceneRenderPerformanceMetrics(scene, renderState, task); + // sceneRenderPerformanceMetrics(scene, renderState, task); // contactSolverDebugDraw(&gContactSolver, renderState); } @@ -214,12 +213,7 @@ int sceneOpenPortal(struct Scene* scene, struct Transform* at, int portalIndex, for (int i = surfaceMapping.minPortalIndex; i < surfaceMapping.maxPortalIndex; ++i) { if (portalSurfaceGenerate(&gCurrentLevel->portalSurfaces[i], at, NULL, NULL)) { - // struct Vector3 portalForward; - // quatMultVector(&at->rotation, &gForward, &portalForward); - // // TODO remove once there is a hole in the wall - // vector3AddScaled(&at->position, &portalForward, (portalIndex == 0) ? -0.1f : 0.1f, &at->position); - - soundPlayerPlay(soundsPortalEnter, 1.0f, 1.0f); + soundPlayerPlay(soundsPortalOpen2, 1.0f, 1.0f); scene->portals[portalIndex].transform = *at; gCollisionScene.portalTransforms[portalIndex] = &scene->portals[portalIndex].transform; diff --git a/src/scene/scene.h b/src/scene/scene.h index 6280908..9b51778 100644 --- a/src/scene/scene.h +++ b/src/scene/scene.h @@ -22,6 +22,8 @@ struct Scene { OSTime lastFrameTime; }; +extern struct Scene gScene; + struct GraphicsTask; void sceneInit(struct Scene* scene);