private static void ProcessCatalog(ManagedPokemonCatalog catalog, ISet <string> fileNames, string root) { foreach (var catalogEntry in catalog.Entries) { fileNames.Add(catalogEntry.ModelPath); fileNames.Add(catalogEntry.ConfigurationPath); var archive = new GFPAK(Path.Combine(root, catalogEntry.PackagePath)); var model = PokemonModel.GetRootAsPokemonModel(archive.GetFile(catalogEntry.ModelPath).Span.ToByteBuffer()); var modelPath = Path.GetDirectoryName(catalogEntry.ModelPath); fileNames.Add(Path.Combine(modelPath, "__ArchiveShader.bnsh").UnixPath(false)); fileNames.Add(Path.Combine(modelPath, "__Combined.bntx").UnixPath(false)); for (var i = 0; i < model.TexturesLength; ++i) { fileNames.Add(Path.Combine(modelPath, model.Textures(i) + ".bntx").UnixPath(false)); } for (var i = 0; i < model.ShaderNamesLength; ++i) { var shader = model.ShaderNames(i); // NOICE! fileNames.Add(Path.Combine(modelPath, shader + ".bnsh").UnixPath(false)); fileNames.Add(Path.Combine(modelPath, shader + ".bnsh_fsh").UnixPath(false)); fileNames.Add(Path.Combine(modelPath, shader + ".bnsh_gsh").UnixPath(false)); fileNames.Add(Path.Combine(modelPath, shader + ".bnsh_vsh").UnixPath(false)); fileNames.Add(Path.Combine(modelPath, $"ArchiveShader-{shader}.bnsh").UnixPath(false)); } var name = Path.GetFileName(Path.GetDirectoryName(catalogEntry.ConfigurationPath)); foreach (var animationConfig in catalogEntry.AnimationSets.Values) { fileNames.Add(animationConfig); var animationPath = Path.GetDirectoryName(animationConfig); fileNames.Add(Path.Combine(animationPath, name + ".gfbanm").UnixPath(false)); var config = PokemonAnimationConfig.GetRootAsPokemonAnimationConfig(archive.GetFile(animationConfig).Span.ToByteBuffer()); var animationData = config.AnimationData.GetValueOrDefault(); for (var i = 0; i < animationData.ReferencesLength; ++i) { fileNames.Add(Path.Combine(animationPath, animationData.References(i).GetValueOrDefault().Path).UnixPath(false)); } } } }
public static GLTFRoot ExportModel(string path) { using var stream = File.OpenRead(path); var pokemonModel = PokemonModel.GetRootAsPokemonModel(stream.ToByteBuffer()); var bufferRoot = Path.GetDirectoryName(path); var bufferRootFile = Path.Combine(bufferRoot, $"{Path.GetFileNameWithoutExtension(path)}.mdlbin"); using var buffer = File.OpenWrite(bufferRootFile); buffer.SetLength(0); var gltfRoot = new GLTFRoot { Asset = new GLTFAsset { Generator = "GFLX", Copyright = "2019 GameFreak - Pokemon Company", Version = "2.0" } }; var gltfBuffer = gltfRoot.Buffers.Count; var materials = DeconstructMaterials(pokemonModel, gltfRoot); var scene = new GLTFScene(); for (var i = 0; i < pokemonModel.VisualGroupLength; ++i) { var group = pokemonModel.VisualGroup(i).GetValueOrDefault(); var mesh = pokemonModel.Meshes((int)group.MeshId).GetValueOrDefault(); var bone = pokemonModel.Bones((int)group.BoneId).GetValueOrDefault(); var attributes = DeconstructVbo(mesh, gltfRoot, buffer, gltfBuffer); var node = new GLTFMesh { Name = bone.Name }; for (var j = 0; j < mesh.IndiceBufferLength; ++j) { var primitive = mesh.IndiceBuffer(j).GetValueOrDefault(); node.Primitives.Add(new GLTFMeshPrimitive { Attributes = attributes, Indices = gltfRoot.Accessors.Count, Mode = GLTFDrawMode.Triangles, Material = materials[primitive.MaterialId] }); gltfRoot.Accessors.Add(new GLTFAccessor { BufferView = gltfRoot.BufferViews.Count, ByteOffset = 0, ComponentType = GLTFComponentType.UnsignedShort, Count = (uint)primitive.IndicesLength, Type = GLTFAccessorAttributeType.SCALAR }); var targetBuffer = MemoryMarshal.Cast <ushort, byte>(primitive.GetIndicesBytes()); gltfRoot.BufferViews.Add(new GLTFBufferView { Buffer = gltfBuffer, ByteOffset = (uint)buffer.Position, ByteLength = (uint)targetBuffer.Length }); buffer.Write(targetBuffer); } scene.Nodes.Add(gltfRoot.Nodes.Count); gltfRoot.Nodes.Add(new GLTFNode { Mesh = gltfRoot.Meshes.Count, Name = node.Name }); gltfRoot.Meshes.Add(node); } gltfRoot.Scenes.Add(scene); gltfRoot.Buffers.Add(new GLTFBuffer { Uri = Path.GetFileName(bufferRootFile), ByteLength = (uint)buffer.Length }); return(gltfRoot); }