From 134cd46d40326b1fa64cb1fe44c173ff2596c844 Mon Sep 17 00:00:00 2001 From: James Lambert Date: Sat, 3 Sep 2022 19:14:07 -0600 Subject: [PATCH] work on textures with palletes --- skelatool64/main.cpp | 20 +- skelatool64/schema/material-schema.json | 3 + skelatool64/src/CommandLineParser.cpp | 5 + skelatool64/src/CommandLineParser.h | 1 + skelatool64/src/DisplayListSettings.h | 1 + skelatool64/src/MeshWriter.cpp | 15 +- skelatool64/src/MeshWriter.h | 1 + skelatool64/src/StringUtils.h | 2 + skelatool64/src/StringUtls.cpp | 16 ++ .../MaterialGenerator.cpp | 22 +- skelatool64/src/materials/Material.cpp | 2 +- skelatool64/src/materials/Material.h | 1 + skelatool64/src/materials/MaterialParser.cpp | 8 +- skelatool64/src/materials/MaterialParser.h | 1 + skelatool64/src/materials/MaterialState.cpp | 50 +++++ .../src/materials/MaterialTranslator.cpp | 206 ++++++++++++++++++ .../src/materials/MaterialTranslator.h | 11 + skelatool64/src/materials/TextureCache.cpp | 12 + skelatool64/src/materials/TextureCache.h | 2 + .../src/materials/TextureDefinition.cpp | 52 ++++- skelatool64/src/materials/TextureDefinition.h | 11 + 21 files changed, 425 insertions(+), 17 deletions(-) create mode 100644 skelatool64/src/materials/MaterialTranslator.cpp create mode 100644 skelatool64/src/materials/MaterialTranslator.h diff --git a/skelatool64/main.cpp b/skelatool64/main.cpp index bb065ad..19ee99e 100644 --- a/skelatool64/main.cpp +++ b/skelatool64/main.cpp @@ -23,6 +23,8 @@ #include "src/definition_generator/LevelGenerator.h" #include "src/definition_generator/TriggerGenerator.h" #include "src/materials/MaterialState.h" +#include "src/materials/MaterialTranslator.h" +#include "src/StringUtils.h" void handler(int sig) { void *array[10]; @@ -42,6 +44,7 @@ bool parseMaterials(const std::string& filename, DisplayListSettings& output) { std::fstream file(filename, std::ios::in); struct ParseResult parseResult(DirectoryName(filename)); + parseResult.mForcePallete = output.mForcePallete; parseMaterialFile(file, parseResult); output.mMaterials.insert(parseResult.mMaterialFile.mMaterials.begin(), parseResult.mMaterialFile.mMaterials.end()); @@ -106,12 +109,23 @@ int main(int argc, char *argv[]) { settings.mExportAnimation = args.mExportAnimation; settings.mExportGeometry = args.mExportGeometry; settings.mBonesAsVertexGroups = args.mBonesAsVertexGroups; + settings.mForcePallete = args.mForcePallete; bool hasError = false; for (auto materialFile = args.mMaterialFiles.begin(); materialFile != args.mMaterialFiles.end(); ++materialFile) { - if (!parseMaterials(*materialFile, settings)) { - hasError = true; + if (EndsWith(*materialFile, ".yaml") || EndsWith(*materialFile, ".yml") || EndsWith(*materialFile, ".json")) { + if (!parseMaterials(*materialFile, settings)) { + hasError = true; + } + } else { + aiScene* materialScene = loadScene(*materialFile, false, settings.mVertexCacheSize, 0); + + if (!materialScene) { + hasError = true; + } + + fillMissingMaterials(gTextureCache, materialScene, settings); } } @@ -142,6 +156,8 @@ int main(int argc, char *argv[]) { if (!scene) { return 1; } + + fillMissingMaterials(gTextureCache, scene, settings); } std::cout << "Saving to " << args.mOutputFile << std::endl; diff --git a/skelatool64/schema/material-schema.json b/skelatool64/schema/material-schema.json index b11d996..fc210ef 100755 --- a/skelatool64/schema/material-schema.json +++ b/skelatool64/schema/material-schema.json @@ -703,6 +703,9 @@ }, "normalSource": { "enum": ["normal", "tangent", "-tangent", "bitangent", "-bitangent"] + }, + "excludeFromOutput": { + "type": "boolean" } } } diff --git a/skelatool64/src/CommandLineParser.cpp b/skelatool64/src/CommandLineParser.cpp index 6ef3cce..1024c5e 100644 --- a/skelatool64/src/CommandLineParser.cpp +++ b/skelatool64/src/CommandLineParser.cpp @@ -55,6 +55,8 @@ bool parseCommandLineArguments(int argc, char *argv[], struct CommandLineArgumen output.mDefaultMaterial = curr; } else if (lastParameter == "force-material") { output.mForceMaterialName = curr; + } else if (lastParameter == "pallete") { + output.mForcePallete = curr; } lastParameter = ""; @@ -82,6 +84,9 @@ bool parseCommandLineArguments(int argc, char *argv[], struct CommandLineArgumen strcmp(curr, "-r") == 0 || strcmp(curr, "--rotate") == 0) { lastParameter = "rotate"; + } else if ( + strcmp(curr, "--pallete") == 0) { + lastParameter = "pallete"; } else if ( strcmp(curr, "-a") == 0 || strcmp(curr, "--animations-only") == 0) { diff --git a/skelatool64/src/CommandLineParser.h b/skelatool64/src/CommandLineParser.h index f584e40..b6d312e 100644 --- a/skelatool64/src/CommandLineParser.h +++ b/skelatool64/src/CommandLineParser.h @@ -22,6 +22,7 @@ struct CommandLineArguments { std::vector mMaterialFiles; std::string mDefaultMaterial; std::string mForceMaterialName; + std::string mForcePallete; float mFixedPointScale; float mModelScale; bool mExportAnimation; diff --git a/skelatool64/src/DisplayListSettings.h b/skelatool64/src/DisplayListSettings.h index 1e99c1f..4ae5b3c 100644 --- a/skelatool64/src/DisplayListSettings.h +++ b/skelatool64/src/DisplayListSettings.h @@ -21,6 +21,7 @@ struct DisplayListSettings { std::map> mMaterials; std::string mDefaultMaterialName; std::string mForceMaterialName; + std::string mForcePallete; MaterialState mDefaultMaterialState; aiQuaternion mRotateModel; bool mExportAnimation; diff --git a/skelatool64/src/MeshWriter.cpp b/skelatool64/src/MeshWriter.cpp index 24df917..7da5197 100644 --- a/skelatool64/src/MeshWriter.cpp +++ b/skelatool64/src/MeshWriter.cpp @@ -9,7 +9,7 @@ MaterialCollector::MaterialCollector(): mSceneCount(0) {} -void useTexture(std::set>& usedTextures, std::shared_ptr texture, CFileDefinition& fileDefinition, const std::string& fileSuffix) { +void useTexture(std::set>& usedTextures, std::set>& usedPalletes, std::shared_ptr texture, CFileDefinition& fileDefinition, const std::string& fileSuffix) { if (usedTextures.find(texture) != usedTextures.end()) { return; } @@ -17,6 +17,14 @@ void useTexture(std::set>& usedTextures, std: usedTextures.insert(texture); fileDefinition.AddDefinition(std::move(texture->GenerateDefinition(fileDefinition.GetUniqueName(texture->Name()), fileSuffix))); + + std::shared_ptr pallete = texture->GetPallete(); + if (!pallete || usedPalletes.find(pallete) != usedPalletes.end()) { + return; + } + + usedPalletes.insert(pallete); + fileDefinition.AddDefinition(std::move(pallete->GenerateDefinition(fileDefinition.GetUniqueName(pallete->Name()), fileSuffix))); } void MaterialCollector::UseMaterial(const std::string& material, DisplayListSettings& settings) { @@ -50,7 +58,7 @@ void MaterialCollector::GenerateMaterials(DisplayListSettings& settings, CFileDe 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); + useTexture(mUsedTextures, mUsedPalletes, tile->texture, fileDefinition, fileSuffix); } } @@ -68,6 +76,7 @@ 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; + std::set> usedPalletes; for (auto chunk = renderChunks.begin(); chunk != renderChunks.end(); ++chunk) { if (materials) { @@ -86,7 +95,7 @@ void generateMeshIntoDLWithMaterials(const aiScene* scene, CFileDefinition& file 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); + useTexture(usedTextures, usedPalletes, tile->texture, fileDefinition, modelSuffix); } } diff --git a/skelatool64/src/MeshWriter.h b/skelatool64/src/MeshWriter.h index fa0b3e7..0398cd3 100644 --- a/skelatool64/src/MeshWriter.h +++ b/skelatool64/src/MeshWriter.h @@ -21,6 +21,7 @@ public: unsigned mSceneCount; std::set> mUsedTextures; + std::set> mUsedPalletes; std::map mMaterialUseCount; std::map mMaterialNameMapping; std::map mResourceNameMapping; diff --git a/skelatool64/src/StringUtils.h b/skelatool64/src/StringUtils.h index 7e0a1d9..98927e8 100644 --- a/skelatool64/src/StringUtils.h +++ b/skelatool64/src/StringUtils.h @@ -14,6 +14,8 @@ void makeCCompatible(std::string& target); bool StartsWith(const std::string& input, const std::string& prefix); +bool EndsWith(const std::string& input, const std::string& suffix); + void SplitString(const std::string& input, char delimeter, std::vector& output); #endif \ No newline at end of file diff --git a/skelatool64/src/StringUtls.cpp b/skelatool64/src/StringUtls.cpp index e5a6bef..fe24568 100644 --- a/skelatool64/src/StringUtls.cpp +++ b/skelatool64/src/StringUtls.cpp @@ -119,6 +119,22 @@ bool StartsWith(const std::string& input, const std::string& prefix) { return true; } +bool EndsWith(const std::string& input, const std::string& suffix) { + if (suffix.length() > input.length()) { + return false; + } + + unsigned indexOffset = input.size() - suffix.size(); + + for (unsigned i = 0; i < suffix.length(); ++i) { + if (input[i + indexOffset] != suffix[i]) { + return false; + } + } + + return true; +} + void SplitString(const std::string& input, char delimeter, std::vector& output) { std::size_t lastStart = 0; std::size_t curr = 0; diff --git a/skelatool64/src/definition_generator/MaterialGenerator.cpp b/skelatool64/src/definition_generator/MaterialGenerator.cpp index 0c817f9..77dc090 100644 --- a/skelatool64/src/definition_generator/MaterialGenerator.cpp +++ b/skelatool64/src/definition_generator/MaterialGenerator.cpp @@ -34,11 +34,21 @@ int sortOrderForMaterial(const Material& material) { void MaterialGenerator::GenerateDefinitions(const aiScene* scene, CFileDefinition& fileDefinition) { std::set> textures; + std::set> palletes; for (auto& entry : mSettings.mMaterials) { + if (entry.second->mExcludeFromOutut) { + continue; + } + for (int i = 0; i < 8; ++i) { - if (entry.second->mState.tiles[i].texture) { - textures.insert(entry.second->mState.tiles[i].texture); + std::shared_ptr texture = entry.second->mState.tiles[i].texture; + if (texture) { + textures.insert(texture); + + if (texture->GetPallete()) { + palletes.insert(texture->GetPallete()); + } } } } @@ -46,6 +56,10 @@ void MaterialGenerator::GenerateDefinitions(const aiScene* scene, CFileDefinitio for (auto& texture : textures) { fileDefinition.AddDefinition(std::move(texture->GenerateDefinition(fileDefinition.GetUniqueName(texture->Name()), "_mat"))); } + + for (auto& pallete : palletes) { + fileDefinition.AddDefinition(std::move(pallete->GenerateDefinition(fileDefinition.GetUniqueName(pallete->Name()), "_mat"))); + } int index = 0; @@ -55,6 +69,10 @@ void MaterialGenerator::GenerateDefinitions(const aiScene* scene, CFileDefinitio std::vector> materialsAsVector; for (auto& entry : mSettings.mMaterials) { + if (entry.second->mExcludeFromOutut) { + continue; + } + materialsAsVector.push_back(entry.second); } diff --git a/skelatool64/src/materials/Material.cpp b/skelatool64/src/materials/Material.cpp index 6d5eb35..abb166d 100644 --- a/skelatool64/src/materials/Material.cpp +++ b/skelatool64/src/materials/Material.cpp @@ -4,7 +4,7 @@ #include "../StringUtils.h" #include "../CFileDefinition.h" -Material::Material(const std::string& name): mName(name), mNormalSource(NormalSource::Normal) {} +Material::Material(const std::string& name): mName(name), mNormalSource(NormalSource::Normal), mExcludeFromOutut(false) {} void Material::Write(CFileDefinition& fileDef, const MaterialState& from, StructureDataChunk& output) { generateMaterial(fileDef, from, mState, output); diff --git a/skelatool64/src/materials/Material.h b/skelatool64/src/materials/Material.h index f1b466b..ba99f7f 100644 --- a/skelatool64/src/materials/Material.h +++ b/skelatool64/src/materials/Material.h @@ -31,6 +31,7 @@ public: MaterialState mState; std::map mProperties; NormalSource mNormalSource; + bool mExcludeFromOutut; void Write(CFileDefinition& fileDef, const MaterialState& from, StructureDataChunk& output); diff --git a/skelatool64/src/materials/MaterialParser.cpp b/skelatool64/src/materials/MaterialParser.cpp index 37af37b..3c5ac6e 100644 --- a/skelatool64/src/materials/MaterialParser.cpp +++ b/skelatool64/src/materials/MaterialParser.cpp @@ -14,8 +14,6 @@ #include "./RenderMode.h" #include "CombineMode.h" -TextureCache gTextureCache; - ParseError::ParseError(const std::string& message) : mMessage(message) { @@ -229,7 +227,7 @@ std::shared_ptr parseTextureDefinition(const YAML::Node& node } std::string filename; - std::string palleteFilename; + std::string palleteFilename = output.mForcePallete; bool hasFormat = false; G_IM_FMT requestedFormat; @@ -767,6 +765,10 @@ std::shared_ptr parseMaterial(const std::string& name, const YAML::Nod material->mNormalSource = parseMaterialNormalSource(node["normalSource"]); + auto excludeFromOutput = node["excludeFromOutput"]; + + material->mExcludeFromOutut = excludeFromOutput.IsDefined() && excludeFromOutput.as(); + auto properties = node["properties"]; if (properties.IsDefined() && properties.IsMap()) { diff --git a/skelatool64/src/materials/MaterialParser.h b/skelatool64/src/materials/MaterialParser.h index 49c99e7..8a2fb94 100644 --- a/skelatool64/src/materials/MaterialParser.h +++ b/skelatool64/src/materials/MaterialParser.h @@ -20,6 +20,7 @@ struct ParseError { struct ParseResult { ParseResult(const std::string& insideFolder); std::string mInsideFolder; + std::string mForcePallete; MaterialFile mMaterialFile; std::vector mErrors; }; diff --git a/skelatool64/src/materials/MaterialState.cpp b/skelatool64/src/materials/MaterialState.cpp index 8ef804f..4d3b170 100644 --- a/skelatool64/src/materials/MaterialState.cpp +++ b/skelatool64/src/materials/MaterialState.cpp @@ -424,10 +424,60 @@ void generateTile(CFileDefinition& fileDef, const MaterialState& from, const Til bool needsToLoadImage = to.texture != nullptr; + std::shared_ptr palleteToLoad = to.texture ? to.texture->GetPallete() : nullptr; + for (int i = 0; i < MAX_TILE_COUNT && needsToLoadImage; ++i) { if (from.tiles[i].texture == to.texture && from.tiles[i].tmem == to.tmem) { needsToLoadImage = false; } + + if (from.tiles[i].texture && from.tiles[i].texture->GetPallete() == palleteToLoad) { + palleteToLoad = nullptr; + } + } + + if (palleteToLoad) { + std::string palleteName; + if (!fileDef.GetResourceName(palleteToLoad.get(), palleteName)) { + std::cerr << "Texture " << palleteToLoad->Name() << " needs to be added to the file definition before being used in a material" << std::endl; + return; + } + + output.Add(std::unique_ptr(new MacroDataChunk("gsDPTileSync"))); + + std::unique_ptr setTextureImage(new MacroDataChunk("gsDPSetTextureImage")); + setTextureImage->AddPrimitive(nameForImageFormat(G_IM_FMT::G_IM_FMT_RGBA)); + setTextureImage->AddPrimitive(std::string(nameForImageSize(G_IM_SIZ::G_IM_SIZ_16b)) + "_LOAD_BLOCK"); + setTextureImage->AddPrimitive(1); + setTextureImage->AddPrimitive(palleteName); + output.Add(std::move(setTextureImage)); + + std::unique_ptr setTile(new MacroDataChunk("gsDPSetTile")); + setTile->AddPrimitive(nameForImageFormat(G_IM_FMT::G_IM_FMT_RGBA)); + setTile->AddPrimitive(std::string(nameForImageSize(G_IM_SIZ::G_IM_SIZ_16b)) + "_LOAD_BLOCK"); + setTile->AddPrimitive(0); + setTile->AddPrimitive(256); + setTile->AddPrimitive("G_TX_LOADTILE"); + setTile->AddPrimitive(0); + setTile->AddPrimitive(buildClampAndWrap(false, false)); + setTile->AddPrimitive(0); + setTile->AddPrimitive(0); + setTile->AddPrimitive(buildClampAndWrap(false, false)); + setTile->AddPrimitive(0); + setTile->AddPrimitive(0); + output.Add(std::move(setTile)); + + output.Add(std::unique_ptr(new MacroDataChunk("gsDPLoadSync"))); + + std::unique_ptr loadBlock(new MacroDataChunk("gsDPLoadBlock")); + loadBlock->AddPrimitive("G_TX_LOADTILE"); + loadBlock->AddPrimitive(0); + loadBlock->AddPrimitive(0); + loadBlock->AddPrimitive(palleteToLoad->LoadBlockSize()); + loadBlock->AddPrimitive(palleteToLoad->DTX()); + output.Add(std::move(loadBlock)); + + output.Add(std::unique_ptr(new MacroDataChunk("gsDPPipeSync"))); } if (needsToLoadImage) { diff --git a/skelatool64/src/materials/MaterialTranslator.cpp b/skelatool64/src/materials/MaterialTranslator.cpp new file mode 100644 index 0000000..ce30fd6 --- /dev/null +++ b/skelatool64/src/materials/MaterialTranslator.cpp @@ -0,0 +1,206 @@ +#include "MaterialTranslator.h" + +#include "MaterialEnums.h" + +void loadTextureFromAiMaterial(TextureCache& cache, Material& material, aiString filename, aiTextureMapMode textureMapMode, DisplayListSettings& settings) { + G_IM_FMT fmt; + G_IM_SIZ siz; + TextureDefinition::DetermineIdealFormat(filename.C_Str(), fmt, siz); + std::shared_ptr useTexture = cache.GetTexture(filename.C_Str(), fmt, siz, (TextureDefinitionEffect)0, settings.mForcePallete); + + TileState& state = material.mState.tiles[0]; + + state.isOn = true; + state.texture = useTexture; + + state.sCoord.mask = log2(state.texture->Width()); + state.tCoord.mask = log2(state.texture->Height()); + + state.sCoord.limit = (state.texture->Width() - 1) * 4; + state.tCoord.limit = (state.texture->Height() - 1) * 4; + + if (textureMapMode == aiTextureMapMode_Wrap) { + state.sCoord.wrap = true; + state.tCoord.wrap = true; + + state.sCoord.mirror = false; + state.tCoord.mirror = false; + } else if (textureMapMode == aiTextureMapMode_Mirror) { + state.sCoord.wrap = true; + state.tCoord.wrap = true; + + state.sCoord.mirror = true; + state.tCoord.mirror = true; + } else { + state.sCoord.wrap = false; + state.tCoord.wrap = false; + + state.sCoord.mirror = false; + state.tCoord.mirror = false; + } +} + +#define TEXTURE_LIT "texture_lit" +#define TEXTURE_UNLIT "texture_unlit" +#define SOLID_LIT "solid_lit" +#define SOLID_UNLIT "solid_unlit" + +void fillDefaultMaterials(DisplayListSettings& settings) { + if (settings.mMaterials.find(TEXTURE_LIT) == settings.mMaterials.end()) { + std::shared_ptr textureLit(new Material(TEXTURE_LIT)); + + textureLit->mState.hasCombineMode = true; + textureLit->mState.cycle1Combine.color[0] = ColorCombineSource::ShadeColor; + textureLit->mState.cycle1Combine.color[1] = ColorCombineSource::_0; + textureLit->mState.cycle1Combine.color[2] = ColorCombineSource::Texel0; + textureLit->mState.cycle1Combine.color[3] = ColorCombineSource::_0; + + textureLit->mState.cycle1Combine.alpha[0] = AlphaCombineSource::_0; + textureLit->mState.cycle1Combine.alpha[1] = AlphaCombineSource::_0; + textureLit->mState.cycle1Combine.alpha[2] = AlphaCombineSource::_0; + textureLit->mState.cycle1Combine.alpha[3] = AlphaCombineSource::Texture0Alpha; + + textureLit->mState.geometryModes.SetFlag((int)GeometryMode::G_LIGHTING, true); + textureLit->mState.geometryModes.SetFlag((int)GeometryMode::G_SHADE, true); + + textureLit->mExcludeFromOutut = true; + + settings.mMaterials[TEXTURE_LIT] = textureLit; + } + + if (settings.mMaterials.find(TEXTURE_UNLIT) == settings.mMaterials.end()) { + std::shared_ptr textureUnlit(new Material(TEXTURE_LIT)); + + textureUnlit->mState.hasCombineMode = true; + textureUnlit->mState.cycle1Combine.color[0] = ColorCombineSource::_0; + textureUnlit->mState.cycle1Combine.color[1] = ColorCombineSource::_0; + textureUnlit->mState.cycle1Combine.color[2] = ColorCombineSource::_0; + textureUnlit->mState.cycle1Combine.color[3] = ColorCombineSource::Texel0; + + textureUnlit->mState.cycle1Combine.alpha[0] = AlphaCombineSource::_0; + textureUnlit->mState.cycle1Combine.alpha[1] = AlphaCombineSource::_0; + textureUnlit->mState.cycle1Combine.alpha[2] = AlphaCombineSource::_0; + textureUnlit->mState.cycle1Combine.alpha[3] = AlphaCombineSource::Texture0Alpha; + + textureUnlit->mState.geometryModes.SetFlag((int)GeometryMode::G_LIGHTING, false); + textureUnlit->mState.geometryModes.SetFlag((int)GeometryMode::G_SHADE, true); + + textureUnlit->mExcludeFromOutut = true; + + settings.mMaterials[TEXTURE_UNLIT] = textureUnlit; + } + + if (settings.mMaterials.find(SOLID_LIT) == settings.mMaterials.end()) { + std::shared_ptr solidLit(new Material(SOLID_LIT)); + + solidLit->mState.hasCombineMode = true; + solidLit->mState.cycle1Combine.color[0] = ColorCombineSource::ShadeColor; + solidLit->mState.cycle1Combine.color[1] = ColorCombineSource::_0; + solidLit->mState.cycle1Combine.color[2] = ColorCombineSource::PrimitiveColor; + solidLit->mState.cycle1Combine.color[3] = ColorCombineSource::_0; + + solidLit->mState.cycle1Combine.alpha[0] = AlphaCombineSource::_0; + solidLit->mState.cycle1Combine.alpha[1] = AlphaCombineSource::_0; + solidLit->mState.cycle1Combine.alpha[2] = AlphaCombineSource::_0; + solidLit->mState.cycle1Combine.alpha[3] = AlphaCombineSource::PrimitiveAlpha; + + solidLit->mState.geometryModes.SetFlag((int)GeometryMode::G_LIGHTING, true); + solidLit->mState.geometryModes.SetFlag((int)GeometryMode::G_SHADE, true); + + solidLit->mExcludeFromOutut = true; + + settings.mMaterials[SOLID_LIT] = solidLit; + } + + if (settings.mMaterials.find(SOLID_UNLIT) == settings.mMaterials.end()) { + std::shared_ptr solidUnlit(new Material(SOLID_UNLIT)); + + solidUnlit->mState.hasCombineMode = true; + solidUnlit->mState.cycle1Combine.color[0] = ColorCombineSource::_0; + solidUnlit->mState.cycle1Combine.color[1] = ColorCombineSource::_0; + solidUnlit->mState.cycle1Combine.color[2] = ColorCombineSource::_0; + solidUnlit->mState.cycle1Combine.color[3] = ColorCombineSource::PrimitiveColor; + + solidUnlit->mState.cycle1Combine.alpha[0] = AlphaCombineSource::_0; + solidUnlit->mState.cycle1Combine.alpha[1] = AlphaCombineSource::_0; + solidUnlit->mState.cycle1Combine.alpha[2] = AlphaCombineSource::_0; + solidUnlit->mState.cycle1Combine.alpha[3] = AlphaCombineSource::PrimitiveAlpha; + + solidUnlit->mState.geometryModes.SetFlag((int)GeometryMode::G_LIGHTING, true); + solidUnlit->mState.geometryModes.SetFlag((int)GeometryMode::G_SHADE, true); + + solidUnlit->mExcludeFromOutut = true; + + settings.mMaterials[SOLID_UNLIT] = solidUnlit; + } +} + +void fillMissingMaterials(TextureCache& cache, const aiScene* fromScene, DisplayListSettings& settings) { + fillDefaultMaterials(settings); + + for (unsigned i = 0; i < fromScene->mNumMaterials; ++i) { + aiMaterial* material = fromScene->mMaterials[i]; + + std::string materialName = ExtendedMesh::GetMaterialName(material, settings.mForceMaterialName); + + if (settings.mMaterials.find(materialName) != settings.mMaterials.end()) { + // a material already exists with the given name + continue; + } + + aiString diffuseFilename; + aiString emmisiveFilename; + aiColor4D diffuseColor; + aiColor3D emmisiveColor; + aiTextureMapMode diffuseTextureMapmode; + aiTextureMapMode emitTextureMapmode; + + bool hasDiffuseTexture = material->GetTexture(aiTextureType_DIFFUSE, 0, &diffuseFilename, NULL, NULL, NULL, NULL, &diffuseTextureMapmode) == aiReturn_SUCCESS; + bool hasEmmissiveTexture = material->GetTexture(aiTextureType_EMISSIVE, 0, &emmisiveFilename, NULL, NULL, NULL, NULL, &emitTextureMapmode) == aiReturn_SUCCESS; + + material->Get(AI_MATKEY_COLOR_DIFFUSE, diffuseColor); + bool hasEmmisiveColor = material->Get(AI_MATKEY_COLOR_EMISSIVE, emmisiveColor) && emmisiveColor != aiColor3D(0, 0, 0); + + std::string fallbackMaterial; + + if (hasDiffuseTexture) { + fallbackMaterial = TEXTURE_LIT; + } else if (hasEmmissiveTexture) { + fallbackMaterial = TEXTURE_UNLIT; + } else if (hasEmmisiveColor) { + fallbackMaterial = SOLID_LIT; + } else { + fallbackMaterial = SOLID_UNLIT; + } + + auto baseMaterial = settings.mMaterials.find(fallbackMaterial); + + if (baseMaterial == settings.mMaterials.end()) { + // no base material to start with + continue; + } + + std::shared_ptr result(new Material(*baseMaterial->second)); + + result->mName = materialName; + result->mExcludeFromOutut = false; + + if (hasDiffuseTexture) { + loadTextureFromAiMaterial(cache, *result, diffuseFilename, diffuseTextureMapmode, settings); + } else if (hasEmmissiveTexture) { + loadTextureFromAiMaterial(cache, *result, emmisiveFilename, emitTextureMapmode, settings); + } else if (hasEmmisiveColor) { + result->mState.primitiveColor.r = (uint8_t)(emmisiveColor.r * 255.0f); + result->mState.primitiveColor.g = (uint8_t)(emmisiveColor.g * 255.0f); + result->mState.primitiveColor.b = (uint8_t)(emmisiveColor.b * 255.0f); + result->mState.primitiveColor.a = 255; + } else { + result->mState.primitiveColor.r = (uint8_t)(diffuseColor.r * 255.0f); + result->mState.primitiveColor.g = (uint8_t)(diffuseColor.g * 255.0f); + result->mState.primitiveColor.b = (uint8_t)(diffuseColor.b * 255.0f); + result->mState.primitiveColor.a = (uint8_t)(diffuseColor.a * 255.0f); + } + + settings.mMaterials[materialName] = result; + } +} \ No newline at end of file diff --git a/skelatool64/src/materials/MaterialTranslator.h b/skelatool64/src/materials/MaterialTranslator.h new file mode 100644 index 0000000..8717a4f --- /dev/null +++ b/skelatool64/src/materials/MaterialTranslator.h @@ -0,0 +1,11 @@ +#ifndef __MATERIAL_MATERIALTRANSLATOR_H__ +#define __MATERIAL_MATERIALTRANSLATOR_H__ + +#include +#include "./Material.h" +#include "./TextureCache.h" +#include "../DisplayListSettings.h" + +void fillMissingMaterials(TextureCache& cache, const aiScene* fromScene, DisplayListSettings& settings); + +#endif \ No newline at end of file diff --git a/skelatool64/src/materials/TextureCache.cpp b/skelatool64/src/materials/TextureCache.cpp index ff7324c..421540b 100644 --- a/skelatool64/src/materials/TextureCache.cpp +++ b/skelatool64/src/materials/TextureCache.cpp @@ -2,6 +2,8 @@ #include "../FileUtils.h" +TextureCache gTextureCache; + std::shared_ptr TextureCache::GetPallete(const std::string& filename) { auto check = mPalletes.find(filename); @@ -33,6 +35,16 @@ std::shared_ptr TextureCache::GetTexture(const std::string& f pallete = GetPallete(palleteFilename); } + if (pallete) { + format = G_IM_FMT::G_IM_FMT_CI; + + if (pallete->ColorCount() <= 16) { + size = G_IM_SIZ::G_IM_SIZ_4b; + } else { + size = G_IM_SIZ::G_IM_SIZ_8b; + } + } + std::shared_ptr result(new TextureDefinition(filename, format, size, effects, pallete)); mCache[normalizedPath] = result; return result; diff --git a/skelatool64/src/materials/TextureCache.h b/skelatool64/src/materials/TextureCache.h index b13b204..4543d6e 100644 --- a/skelatool64/src/materials/TextureCache.h +++ b/skelatool64/src/materials/TextureCache.h @@ -15,4 +15,6 @@ private: std::map> mCache; }; +extern TextureCache gTextureCache; + #endif \ No newline at end of file diff --git a/skelatool64/src/materials/TextureDefinition.cpp b/skelatool64/src/materials/TextureDefinition.cpp index e050cac..8b9efdb 100644 --- a/skelatool64/src/materials/TextureDefinition.cpp +++ b/skelatool64/src/materials/TextureDefinition.cpp @@ -387,7 +387,8 @@ void selectChannel(cimg_library_suffixed::CImg& input, TextureDef } } -PalleteDefinition::PalleteDefinition(const std::string& filename) { +PalleteDefinition::PalleteDefinition(const std::string& filename): + mName(getBaseName(replaceExtension(filename, "")) + "_tlut") { cimg_library_suffixed::CImg imageData(filename.c_str()); DataChunkStream dataStream; @@ -428,6 +429,46 @@ PixelIu8 PalleteDefinition::FindIndex(PixelRGBAu8 color) const { return PixelIu8(result); } + +std::unique_ptr PalleteDefinition::GenerateDefinition(const std::string& name, const std::string& location) const { + std::unique_ptr dataChunk(new StructureDataChunk()); + + for (unsigned chunkIndex = 0; chunkIndex < mData.size(); ++chunkIndex) { + std::ostringstream stream; + stream << "0x" << std::hex << std::setw(16) << std::setfill('0') << mData[chunkIndex]; + dataChunk->AddPrimitive(stream.str()); + } + + return std::unique_ptr(new DataFileDefinition("u64", name, true, location, std::move(dataChunk), this)); +} + +const std::string& PalleteDefinition::Name() const { + return mName; +} + + +int gSizeInc[] = {3, 1, 0, 0}; +int gSizeShift[] = {2, 1, 0, 0}; + +int PalleteDefinition::LoadBlockSize() const { + return mColors.size() - 1; +} + +#define G_TX_DTX_FRAC 11 + +int PalleteDefinition::DTX() const { + int lineSize = mColors.size() / 4; + + if (!lineSize) { + lineSize = 1; + } + return ((1 << G_TX_DTX_FRAC) + lineSize - 1) / lineSize; +} + +unsigned PalleteDefinition::ColorCount() const { + return mColors.size(); +} + TextureDefinition::TextureDefinition(const std::string& filename, G_IM_FMT fmt, G_IM_SIZ siz, TextureDefinitionEffect effects, std::shared_ptr pallete) : mName(getBaseName(replaceExtension(filename, "")) + "_" + gFormatShortName[(int)fmt] + "_" + gSizeName[(int)siz]), mFmt(fmt), @@ -582,11 +623,6 @@ G_IM_SIZ TextureDefinition::Size() const { return mSiz; } -#define G_TX_DTX_FRAC 11 - -int gSizeInc[] = {3, 1, 0, 0}; -int gSizeShift[] = {2, 1, 0, 0}; - int TextureDefinition::LoadBlockSize() const { return ((Height() * Width() + gSizeInc[(int)mSiz]) >> gSizeShift[(int)mSiz]) - 1; } @@ -625,4 +661,8 @@ PixelRGBAu8 TextureDefinition::GetTwoToneMin() const { PixelRGBAu8 TextureDefinition::GetTwoToneMax() const { return mTwoToneMax; +} + +std::shared_ptr TextureDefinition::GetPallete() const { + return mPallete; } \ No newline at end of file diff --git a/skelatool64/src/materials/TextureDefinition.h b/skelatool64/src/materials/TextureDefinition.h index b0a9fdc..7c68231 100644 --- a/skelatool64/src/materials/TextureDefinition.h +++ b/skelatool64/src/materials/TextureDefinition.h @@ -67,7 +67,16 @@ public: PalleteDefinition(const std::string& filename); PixelIu8 FindIndex(PixelRGBAu8 color) const; + + std::unique_ptr GenerateDefinition(const std::string& name, const std::string& location) const; + + const std::string& Name() const; + + int LoadBlockSize() const; + int DTX() const; + unsigned ColorCount() const; private: + std::string mName; std::vector mColors; std::vector mData; }; @@ -96,6 +105,8 @@ public: PixelRGBAu8 GetTwoToneMin() const; PixelRGBAu8 GetTwoToneMax() const; + + std::shared_ptr GetPallete() const; private: std::string mName; G_IM_FMT mFmt;