예제 #1
0
        public bool Execute(string[] args)
        {
            if (args.Length < 1)
            {
                Console.WriteLine("Expected at least 1 argument.");
                return(false);
            }

            var inputPath = args[0];

            if (!File.Exists(inputPath))
            {
                Console.WriteLine("Input file doesn't exist.");
                return(false);
            }

            var outputPath = Path.ChangeExtension(inputPath, null);

            if (args.Length > 1)
            {
                outputPath = args[1];
            }

            Directory.CreateDirectory(outputPath);

            var fs = new LBFileSystem();

            try
            {
                fs.Load(inputPath);
            }
            catch (Exception)
            {
                Console.WriteLine("Invalid LB file.");
                return(false);
            }

            using ( fs )
            {
                foreach (int file in fs.EnumerateFiles(SearchOption.AllDirectories))
                {
                    var info = fs.GetInfo(file);

                    using (var stream = FileUtils.Create($"{outputPath}{Path.DirectorySeparatorChar}{file:D2}{'_'}{info.UserId:D2}.{info.Extension}"))
                        using (var inputStream = fs.OpenFile(file))
                        {
                            Console.WriteLine($"Extracting: {file}");
                            inputStream.CopyTo(stream);
                        }
                }
            }

            return(true);
        }
예제 #2
0
        private static void ReplaceF1Test()
        {
            var modelPack = new ModelPack();
            var model     = new Model();

            model.Nodes.Add(new Node {
                Name = "model"
            });
            modelPack.Models.Add(model);
            modelPack.Replace("f1test.fbx");

            var lb = new LBFileSystem();

            lb.Load(@"D:\Modding\DDS3\Nocturne\_HostRoot\dds3data\fld\f\f037\_f037_027.LB");

            var f1Handle = lb.GetHandle("F1");

            FieldScene f1;

            using (var stream = lb.OpenFile(f1Handle))
                f1 = new FieldScene(stream, true);

            f1.Objects.RemoveAll(x => x.ResourceType == FieldObjectResourceType.Model);
            f1.Objects.Clear();
            f1.Objects.Add(new FieldObject()
            {
                Id = 0, Name = "model", Transform = new FieldObjectTransform(), Resource = modelPack.Models[0]
            });
            ExportObj(f1);

            lb.AddFile(f1Handle, f1.Save(), true, ConflictPolicy.Replace);

            if (modelPack.TexturePack != null)
            {
                var tbHandle = lb.GetHandle("TBN");
                lb.AddFile(tbHandle, modelPack.TexturePack.Save(), true, ConflictPolicy.Replace);
            }

            lb.Save(@"D:\Modding\DDS3\Nocturne\_HostRoot\dds3data\fld\f\f037\f037_027.LB");
        }
예제 #3
0
        private static void Main(string[] args)
        {
            {
                File.Delete("test.fbx");
                var modelPack = new ModelPack(@"D:\dumps\smt3_ntsc\DDS3\model\field\player_a.PB");
                //var modelPack = new ModelPack( @"D:\dumps\smt3_ntsc\DDS3\model\devil\on\0x126_on.PB");
                FbxModelExporter.Instance.Export(modelPack.Models[0], "test.fbx", modelPack.TexturePack);
                return;

                //AssimpModelExporter.Instance.Export( modelPack.Models[ 0 ], "player_a.dae", modelPack.TexturePack );
                //for ( var i = 0; i < modelPack.MotionPacks[ 0 ].Motions.Count; i++ )
                //{
                //    var motion = modelPack.MotionPacks[ 0 ].Motions[ i ];
                //    if ( motion == null )
                //        continue;

                //    AssimpMotionExporter.Instance.Export( modelPack.Models[ 0 ], motion, $"player_a_motion_{i:D2}.dae" );
                //}

                var newMotion =
                    AssimpMotionImporter.Instance.Import(@"D:\Users\smart\Desktop\nocturne_player_a_fortnite.fbx",
                                                         new AssimpMotionImporter.Config
                {
                    NodeIndexResolver = n => modelPack.Models[0].Nodes.FindIndex(x => x.Name == n)
                });
                for (int i = 0; i < modelPack.MotionPacks[0].Motions.Count; i++)
                {
                    modelPack.MotionPacks[0].Motions[i] = newMotion;
                }

                modelPack.Save(@"D:\Modding\DDS3\Nocturne\_HostRoot\dds3data\model\field\player_a.PB");
            }

            {
                var lb = new LBFileSystem();
                lb.Load(@"D:\Modding\DDS3\Nocturne\_HostRoot\dds3data\fld\f\f037\_f037_027.LB");

                var f1Handle = lb.GetHandle("F1");

                FieldScene f1;
                using (var stream = lb.OpenFile(f1Handle))
                    f1 = new FieldScene(stream, true);

                foreach (var obj in f1.Objects)
                {
                    switch (obj.ResourceType)
                    {
                    case FieldObjectResourceType.Model:
                    {
                        var model = ( Model )obj.Resource;
                        foreach (var material in model.Materials)
                        {
                            if (material.TextureId.HasValue)
                            {
                                material.TextureId = 0;
                            }

                            material.Color1      = material.Color2 = material.Color3 = material.Color4 = material.Color5 = null;
                            material.Float1      = null;
                            material.FloatArray1 = material.FloatArray2 = material.FloatArray3 = null;
                        }

                        foreach (var node in model.Nodes)
                        {
                            if (node.Geometry == null)
                            {
                                continue;
                            }

                            foreach (var _mesh in node.Geometry.Meshes)
                            {
                                if (_mesh is MeshType1 mesh)
                                {
                                    foreach (var batch in mesh.Batches)
                                    {
                                        batch.Flags &= ~MeshFlags.Normal;
                                        batch.Flags &= ~MeshFlags.Color;
                                    }
                                }
                            }
                        }
                    }
                    break;

                    case FieldObjectResourceType.Type3:
                        break;

                    case FieldObjectResourceType.TextureListFileName:
                        break;

                    case FieldObjectResourceType.Effect:
                        break;

                    case FieldObjectResourceType.Light:
                        break;
                    }
                }
                ExportObj(f1);

                lb.AddFile(f1Handle, f1.Save(), true, ConflictPolicy.Replace);

                var tbHandle    = lb.GetHandle("TBN");
                var texturePack = new TexturePack();
                texturePack.Textures.Add(new Texture(new Bitmap(@"D:\Modding\Tools\magenta.png")));
                lb.AddFile(tbHandle, texturePack.Save(), true, ConflictPolicy.Replace);

                lb.Save(@"D:\Modding\DDS3\Nocturne\_HostRoot\dds3data\fld\f\f037\f037_027.LB");
            }

            //OpenAndSaveModelPackTest();
            //ReplaceF1Test();
            //ReplaceModelTest();
            //OpenAndSaveModelPackBatchTest();
            //return;
            //ExportObj( new ModelPack( @"D:\Modding\DDS3\Nocturne\_HostRoot\dds3data\model\field\player_b.PB" ) );
            //return;
            //OpenAndSaveModelPackBatchTest();return;
            //OpenAndSaveFieldSceneBatchTest();return;
            //ReplaceModelTest();return;

            //var modelPack = new ModelPack( @"..\..\..\..\Resources\player_a.PB" );
            //var modelPack = new ModelPack( @"D:\Modding\DDS3\Nocturne\_HostRoot\dds3data\model\field\player_a.PB" );

            //using ( var writer = File.CreateText( "test.obj" ) )
            //{
            //    var vertexBaseIndex = 0;

            //    foreach ( var model in modelPack.Models )
            //    {
            //        foreach ( var node in model.Nodes )
            //        {
            //            if ( node.Geometry == null )
            //                continue;

            //            for ( var meshIndex = 0; meshIndex < node.Geometry.Meshes.Count; meshIndex++ )
            //            {
            //                var _mesh = node.Geometry.Meshes[ meshIndex ];
            //                if ( _mesh.Type != MeshType.Type7 )
            //                    continue;

            //                var mesh = ( MeshType7 ) _mesh;
            //                var positions = new Vector3[mesh.VertexCount];
            //                var normals   = new Vector3[positions.Length];
            //                var weights   = new List<(short NodeIndex, float Weight)>[positions.Length];
            //                var texCoords = new Vector2[positions.Length];
            //                var batchVertexBaseIndex = 0;

            //                foreach ( var batch in mesh.Batches )
            //                {
            //                    for ( var nodeBatchIndex = 0; nodeBatchIndex < batch.NodeBatches.Count; nodeBatchIndex++ )
            //                    {
            //                        var nodeBatch          = batch.NodeBatches[ nodeBatchIndex ];
            //                        var nodeWorldTransform = model.Nodes[ nodeBatch.NodeIndex ].WorldTransform;

            //                        for ( int i = 0; i < nodeBatch.Positions.Length; i++ )
            //                        {
            //                            var position = new Vector3( nodeBatch.Positions[i].X, nodeBatch.Positions[i].Y,
            //                                                        nodeBatch.Positions[i].Z );
            //                            var weight                     = nodeBatch.Positions[i].W;
            //                            var weightedNodeWorldTransform = nodeWorldTransform * weight;
            //                            var weightedWorldPosition      = Vector3.Transform( position, weightedNodeWorldTransform );
            //                            positions[batchVertexBaseIndex + i] += weightedWorldPosition;
            //                            if ( weights[batchVertexBaseIndex + i] == null )
            //                                weights[batchVertexBaseIndex + i] = new List<(short NodeIndex, float Weight)>();
            //                            weights[batchVertexBaseIndex + i].Add( (nodeBatch.NodeIndex, weight) );
            //                            normals[batchVertexBaseIndex + i] += Vector3.TransformNormal( nodeBatch.Normals[i], weightedNodeWorldTransform );
            //                        }
            //                    }

            //                    Array.Copy( batch.TexCoords, 0, texCoords, batchVertexBaseIndex, batch.TexCoords.Length );

            //                    //foreach ( var position in positions )
            //                    //{
            //                    //    writer.WriteLine( $"v {position.X} {position.Y} {position.Z}" );
            //                    //}

            //                    //foreach ( var normal in normals )
            //                    //{
            //                    //    writer.WriteLine( $"vn {normal.X} {normal.Y} {normal.Z}" );
            //                    //}

            //                    //foreach ( var texCoord in batch.TexCoords )
            //                    //{
            //                    //    writer.WriteLine( $"vt {texCoord.X} {texCoord.Y}" );
            //                    //}

            //                    batchVertexBaseIndex += batch.VertexCount;
            //                }

            //                foreach ( var position in positions )
            //                {
            //                    writer.WriteLine( $"v {position.X} {position.Y} {position.Z}" );
            //                }

            //                foreach ( var normal in normals )
            //                {
            //                    writer.WriteLine( $"vn {normal.X} {normal.Y} {normal.Z}" );
            //                }

            //                foreach ( var texCoord in texCoords )
            //                {
            //                    writer.WriteLine( $"vt {texCoord.X} {texCoord.Y}" );
            //                }

            //                //// Find unique node indices used by the mesh (max 4 per mesh!)
            //                //var usedNodeIndices = weights.SelectMany( x => x.Select( y => y.NodeIndex ) ).Distinct().ToList();

            //                //// Calculate node index usage frequency
            //                //var usedNodeIndicesFrequency = new Dictionary<int, int>();
            //                //for ( int i = 0; i < usedNodeIndices.Count; i++ )
            //                //    usedNodeIndicesFrequency[usedNodeIndices[i]] = 0;

            //                //for ( int j = 0; j < positions.Length; j++ )
            //                //{
            //                //    foreach ( var (nodeIndex, _) in weights[j] )
            //                //        ++usedNodeIndicesFrequency[nodeIndex];
            //                //}

            //                //// Sort used node indices by frequency
            //                //usedNodeIndices = usedNodeIndices.OrderBy( x => usedNodeIndicesFrequency[ x ] ).ToList();

            //                //// Start building batches
            //                //var vertexIndexRemap     = new Dictionary<int, int>();
            //                //var batches = new List<MeshType7Batch>();
            //                //batchVertexBaseIndex = 0;

            //                //while ( vertexIndexRemap.Count < positions.Length )
            //                //{
            //                //    var batchVertexCount = Math.Min( 24, positions.Length - vertexIndexRemap.Count );
            //                //    var batch = new MeshType7Batch();
            //                //    var batchVertexIndexRemap = new Dictionary<int, int>();
            //                //    var batchTexCoords = new List<Vector2>();

            //                //    // req. all vertices to use the same set of node indices
            //                //    for ( var i = 0; i < usedNodeIndices.Count; i++ )
            //                //    {
            //                //        var nodeIndex = usedNodeIndices[i];
            //                //        var nodeWorldTransform = model.Nodes[nodeIndex].WorldTransform;
            //                //        var nodeWorldTransformInv = nodeWorldTransform.Inverted();

            //                //        // get all verts with this index
            //                //        var nodePositions = new List<Vector4>();
            //                //        var nodeNormals = new List<Vector3>();

            //                //        for ( int j = 0; j < positions.Length; j++ )
            //                //        {
            //                //            // Skip this vertex if it has already been processed before
            //                //            if ( vertexIndexRemap.ContainsKey( j ) )
            //                //                continue;

            //                //            foreach ( (short NodeIndex, float Weight) in weights[j] )
            //                //            {
            //                //                if ( NodeIndex != nodeIndex )
            //                //                    continue;

            //                //                // Transform position and normal to model space
            //                //                var position = Vector3.Transform( positions[j], nodeWorldTransformInv );
            //                //                var normal = Vector3.TransformNormal( normals[j], nodeWorldTransformInv );

            //                //                // Add entry to vertex remap, and add the model space positions and normals to our lists
            //                //                batchVertexIndexRemap[j] = batchVertexBaseIndex + nodePositions.Count;
            //                //                nodePositions.Add( new Vector4( position, Weight ) );
            //                //                nodeNormals.Add( normal );

            //                //                if ( i == 0 )
            //                //                {
            //                //                    // Only add this once, of course
            //                //                    batchTexCoords.Add( texCoords[ j ] );
            //                //                }

            //                //                // Stop looking if we've reached our vertex count
            //                //                if ( nodePositions.Count == batchVertexCount )
            //                //                    goto end;
            //                //            }
            //                //        }

            //                //        end:
            //                //        batch.NodeBatches.Add( new MeshType7NodeBatch()
            //                //        {
            //                //            NodeIndex = nodeIndex,
            //                //            Positions = nodePositions.ToArray(),
            //                //            Normals   = nodeNormals.ToArray()
            //                //        });
            //                //    }

            //                //    batch.TexCoords = batchTexCoords.ToArray();

            //                //    foreach ( var i in batchVertexIndexRemap )
            //                //        vertexIndexRemap.Add( i.Key, i.Value );

            //                //    Debug.Assert( batch.NodeBatches.Count > 0 );
            //                //    Debug.Assert( batch.NodeBatches.TrueForAll( x => x.VertexCount == batch.NodeBatches[ 0 ].VertexCount ) );
            //                //    batches.Add( batch );
            //                //    batchVertexBaseIndex += batchVertexCount;
            //                //}

            //                //var materialIndex = mesh.MaterialIndex;
            //                //var triangles = new Triangle[mesh.TriangleCount];
            //                //for ( var i = 0; i < mesh.Triangles.Length; i++ )
            //                //{
            //                //    ref var triangle = ref triangles[i];
            //                //    triangle.A = ( ushort )vertexIndexRemap[mesh.Triangles[i].A];
            //                //    triangle.B = ( ushort )vertexIndexRemap[mesh.Triangles[i].B];
            //                //    triangle.C = ( ushort )vertexIndexRemap[mesh.Triangles[i].C];
            //                //}

            //                //mesh = new MeshType7();
            //                //mesh.Batches.AddRange( batches );
            //                //mesh.Triangles = triangles;
            //                //mesh.MaterialIndex = materialIndex;
            //                //node.Geometry.Meshes[meshIndex] = mesh;

            //                writer.WriteLine( $"o node_{node.Name}_mesh_{meshIndex}" );
            //                foreach ( var triangle in mesh.Triangles )
            //                {
            //                    writer.WriteLine( "f {0}/{0}/{0} {1}/{1}/{1} {2}/{2}/{2}", vertexBaseIndex + triangle.A + 1, vertexBaseIndex + triangle.B + 1, vertexBaseIndex + triangle.C + 1 );
            //                }

            //                vertexBaseIndex += mesh.VertexCount;
            //            }
            //        }
            //    }
            //}



            //modelPack.Save( @"D:\Modding\DDS3\Nocturne\_HostRoot\dds3data\model\field\player_a.PB" );


            //ReplaceModelTest();
            //return;
            //GenerateMaterialPresets();
            //return;
            //var modelPack = new ModelPack( @"..\..\..\..\Resources\player_a.PB" );
            //foreach ( var material in modelPack.Models[0].Materials )
            //{
            //    Console.WriteLine( MaterialPresetStore.GetPresetId( material ) );
            //}
            //return;
            ////for ( var i = 0; i < modelPack.TexturePack.Count; i++ )
            ////{
            ////    var texture = modelPack.TexturePack[ i ];
            ////    texture.GetBitmap().Save( $"player_a_{i}.png" );
            ////}

            //modelPack.Save( @"D:\Modding\DDS3\Nocturne\_HostRoot\dds3data\model\field\player_a.PB" );
            ////ReplaceModelTest();
            //OpenAndSaveModelPackBatchTest();
        }
예제 #4
0
        public bool Execute(string[] args)
        {
            if (args.Length < 1)
            {
                Console.WriteLine("Expected at least 1 argument");
                return(false);
            }

            var inputPath = args[0];

            if (!Directory.Exists(inputPath))
            {
                Console.WriteLine("Input directory doesn't exist");
                return(false);
            }

            var outputPath = Path.ChangeExtension(inputPath, "LB");

            if (args.Length > 1)
            {
                outputPath = args[1];
            }

            using (var fs = new LBFileSystem())
            {
                foreach (string file in Directory.EnumerateFiles(inputPath, "*.*", SearchOption.AllDirectories))
                {
                    var name = Path.GetFileNameWithoutExtension(file);
                    if (name == null)
                    {
                        continue;
                    }

                    var nameParts = name.Split(new[] { '_' }, StringSplitOptions.RemoveEmptyEntries);

                    if (int.TryParse(nameParts[0], out var handle))
                    {
                        if (nameParts.Length > 1 && short.TryParse(nameParts[1], out var userId))
                        {
                            Console.WriteLine($"Adding file: {file} as: {handle}:{userId}");
                            fs.AddFile(handle, userId, file, ConflictPolicy.Replace);
                        }
                        else
                        {
                            Console.WriteLine($"Adding file: {file} as: {handle}:0");
                            fs.AddFile(handle, file, ConflictPolicy.Replace);
                        }
                    }
                    else
                    {
                        Console.WriteLine($"Adding file: {file}");
                        fs.AddFile(file);
                    }
                }

                Console.WriteLine("Saving...");
                fs.Save(outputPath);
            }

            return(true);
        }
예제 #5
0
        public bool Execute(string[] args)
        {
            if (args.Length < 2)
            {
                Console.WriteLine("Expected at least 2 arguments.");
                return(false);
            }

            var inputPath = args[0];

            if (!File.Exists(inputPath))
            {
                Console.WriteLine("Input file doesn't exist.");
                return(false);
            }

            var fs = new LBFileSystem();

            try
            {
                fs.Load(inputPath);
            }
            catch (Exception)
            {
                Console.WriteLine("Invalid LB file");
                return(false);
            }

            string outputPath = inputPath;

            if (Directory.Exists(args[1]))
            {
                var directoryPath = args[1];

                if (args.Length > 2)
                {
                    outputPath = args[2];
                }

                using ( fs )
                {
                    foreach (string file in Directory.EnumerateFiles(directoryPath, "*.*", SearchOption.AllDirectories))
                    {
                        Console.WriteLine($"Adding/Replacing file: {file}");
                        var name = Path.GetFileNameWithoutExtension(file);
                        if (name == null)
                        {
                            continue;
                        }

                        var nameParts = name.Split(new[] { '_' }, StringSplitOptions.RemoveEmptyEntries);

                        if (int.TryParse(nameParts[0], out var handle))
                        {
                            if (nameParts.Length > 1 && short.TryParse(nameParts[1], out var userId))
                            {
                                fs.AddFile(handle, userId, file, ConflictPolicy.Replace);
                            }
                            else
                            {
                                fs.AddFile(handle, file, ConflictPolicy.Replace);
                            }
                        }
                        else
                        {
                            fs.AddFile(file);
                        }
                    }

                    Console.WriteLine("Saving...");
                    fs.Save(outputPath);
                }
            }
            else
            {
                if (args.Length > 3)
                {
                    outputPath = args[3];
                }

                using ( fs )
                {
                    var entryName      = args[1];
                    var entryNameParts = entryName.Split(new[] { '_' }, StringSplitOptions.RemoveEmptyEntries);

                    if (int.TryParse(entryNameParts[0], out var handle))
                    {
                        if (!fs.Exists(handle))
                        {
                            Console.WriteLine("Specified entry doesn't exist.");
                            return(false);
                        }

                        var filePath = args[2];
                        if (!File.Exists(filePath))
                        {
                            Console.WriteLine("Specified replacement file doesn't exist.");
                            return(false);
                        }

                        Console.WriteLine($"Replacing file: {filePath}");
                        fs.AddFile(handle, filePath, ConflictPolicy.Replace);

                        Console.WriteLine("Saving...");
                        fs.Save(outputPath);
                    }
                }
            }

            return(true);
        }
예제 #6
0
        private static void ConvertAssimpModel()
        {
            switch (Options.OutputFormat)
            {
            case OutputFormat.PB:
            {
                if (Options.PackedModel.ReplaceInput == null)
                {
                    throw new Exception("You must specify a PB replacement input for conversion to PB");
                }

                var modelPack = new ModelPack();
                if (Options.PackedModel.ReplaceInput != null)
                {
                    modelPack.Load(Options.PackedModel.ReplaceInput);
                }

                if (!Options.Assimp.TreatInputAsAnimation)
                {
                    modelPack.Replace(Options.Input, Options.TmxScale, Options.Model.EnableMaterialOverlays, Options.Model.WeightedMeshType,
                                      Options.Model.UnweightedMeshType, Options.Model.MeshWeightLimit, Options.Model.BatchVertexLimit);
                }
                else
                {
                    var newMotion =
                        AssimpMotionImporter.Instance.Import(Options.Input,
                                                             new AssimpMotionImporter.Config
                        {
                            NodeIndexResolver = n => modelPack.Models[Options.PackedModel.ReplaceMotionModelIndex].Nodes.FindIndex(x => x.Name == n)
                        });

                    if (Options.PackedModel.ReplaceMotionIndex < 0 || (Options.PackedModel.ReplaceMotionIndex + 1) >
                        modelPack.MotionPacks[Options.PackedModel.ReplaceMotionPackIndex].Motions.Count)
                    {
                        modelPack.MotionPacks[Options.PackedModel.ReplaceMotionPackIndex].Motions[Options.PackedModel.ReplaceMotionIndex] = newMotion;
                    }
                }

                modelPack.Save(Options.Output);
            }
            break;

            case OutputFormat.F1:
            {
                var modelPack = new ModelPack();
                var model     = new Model();
                model.Nodes.Add(new Node {
                        Name = "model"
                    });
                modelPack.Models.Add(model);
                modelPack.Replace(Options.Input, Options.TmxScale, Options.Model.EnableMaterialOverlays,
                                  Options.Model.WeightedMeshType, Options.Model.UnweightedMeshType, Options.Model.MeshWeightLimit, Options.Model.BatchVertexLimit);

                var lb = new LBFileSystem();
                lb.Load(Options.Field.LbReplaceInput);

                var f1Handle = lb.GetHandle("F1");

                FieldScene f1;
                using (var stream = lb.OpenFile(f1Handle))
                    f1 = new FieldScene(stream, true);

                f1.Objects.RemoveAll(x => x.ResourceType == FieldObjectResourceType.Model);
                f1.Objects.Clear();
                f1.Objects.Add(new FieldObject()
                    {
                        Id = 0, Name = "model", Transform = new FieldObjectTransform(), Resource = modelPack.Models[0]
                    });

                lb.AddFile(f1Handle, f1.Save(), true, ConflictPolicy.Replace);

                if (modelPack.TexturePack != null)
                {
                    var tbHandle = lb.GetHandle("TBN");
                    lb.AddFile(tbHandle, modelPack.TexturePack.Save(), true, ConflictPolicy.Replace);
                }

                lb.Save(Options.Output);
            }
            break;

            default:
                throw new Exception("Unsupported output format");
            }
        }