Example #1
0
        public override object Execute(List <string> args)
        {
            if (args.Count != 2)
            {
                return(false);
            }

            var fileType = args[0];
            var fileName = args[1];

            if (fileType != "obj")
            {
                throw new NotSupportedException(fileType);
            }

            if (Definition.Geometry.Resource == null)
            {
                Console.WriteLine("ERROR: Render geometry does not have a resource associated with it.");
                return(true);
            }

            //
            // Deserialize the resource definition
            //

            var definition = Cache.ResourceCache.GetRenderGeometryApiResourceDefinition(Definition.Geometry.Resource);

            Definition.Geometry.SetResourceBuffers(definition);

            using (var resourceStream = new MemoryStream())
            {
                //
                // Extract the resource data
                //
                var file = new FileInfo(fileName);

                if (!file.Directory.Exists)
                {
                    file.Directory.Create();
                }

                using (var objFile = new StreamWriter(file.Create()))
                {
                    var objExtractor = new ObjExtractor(objFile);

                    foreach (var mesh in Definition.Geometry.Meshes)
                    {
                        var vertexCompressor = new VertexCompressor(Definition.Geometry.Compression[0]);
                        var meshReader       = new MeshReader(Cache.Version, mesh);
                        objExtractor.ExtractMesh(meshReader, vertexCompressor);
                    }

                    objExtractor.Finish();
                }
            }

            Console.WriteLine("Done!");

            return(true);
        }
Example #2
0
        private RenderGeometryCompression CompressVertexBuffer(VertexBufferDefinition vertexBuffer)
        {
            Debug.Assert(vertexBuffer.Format == VertexBufferFormat.Rigid);

            var compression = new RenderGeometryCompression();

            var rigidVertices = new List <RigidVertex>();

            using (var stream = new MemoryStream(vertexBuffer.Data.Data))
            {
                var vertexStream = VertexStreamFactory.Create(DestCache.Version, stream);
                for (int i = 0; i < vertexBuffer.Count; i++)
                {
                    var vertex = vertexStream.ReadRigidVertex();
                    rigidVertices.Add(vertex);
                }
            }

            var positions = rigidVertices.Select(v => v.Position);
            var texCoords = rigidVertices.Select(v => v.Texcoord);

            if (positions != null && positions.Count() > 0)
            {
                compression.X.Lower = Math.Min(compression.X.Lower, positions.Min(v => v.I));
                compression.Y.Lower = Math.Min(compression.Y.Lower, positions.Min(v => v.J));
                compression.Z.Lower = Math.Min(compression.Z.Lower, positions.Min(v => v.K));
                compression.X.Upper = Math.Max(compression.X.Upper, positions.Max(v => v.I));
                compression.Y.Upper = Math.Max(compression.Y.Upper, positions.Max(v => v.J));
                compression.Z.Upper = Math.Max(compression.Z.Upper, positions.Max(v => v.K));
            }
            if (texCoords != null && texCoords.Count() > 0)
            {
                compression.U.Lower = Math.Min(compression.U.Lower, texCoords.Min(v => v.I));
                compression.V.Lower = Math.Min(compression.V.Lower, texCoords.Min(v => v.J));
                compression.U.Upper = Math.Max(compression.U.Upper, texCoords.Max(v => v.I));
                compression.V.Upper = Math.Max(compression.V.Upper, texCoords.Max(v => v.J));
            }

            var compressor = new VertexCompressor(compression);

            using (var outStream = new MemoryStream())
            {
                var outVertexStream = VertexStreamFactory.Create(DestCache.Version, outStream);
                foreach (var vertex in rigidVertices)
                {
                    vertex.Position = compressor.CompressPosition(vertex.Position);
                    vertex.Texcoord = compressor.CompressUv(vertex.Texcoord);
                    outVertexStream.WriteRigidVertex(vertex);
                }

                vertexBuffer.Data.Data = outStream.ToArray();
            }

            return(compression);
        }
        private bool ExtractObj(string variantName, FileInfo modelFile, RenderModel renderModel, RenderGeometryApiResourceDefinition resourceDefinition, Stream resourceStream)
        {
            var meshes           = new Dictionary <string, Mesh>();
            var vertexCompressor = new VertexCompressor(renderModel.Geometry.Compression[0]);

            foreach (var region in renderModel.Regions)
            {
                var regionName = CacheContext.GetString(region.Name);

                foreach (var permutation in region.Permutations)
                {
                    var permutationName = CacheContext.GetString(permutation.Name);

                    if (variantName != "*" && variantName != permutationName)
                    {
                        continue;
                    }

                    for (var i = 0; i < permutation.MeshCount; i++)
                    {
                        var name = $"{regionName}_{permutationName}_{i}";
                        meshes[name] = renderModel.Geometry.Meshes[permutation.MeshIndex + i];
                    }
                }
            }

            if (meshes.Count == 0)
            {
                Console.WriteLine($"ERROR: No meshes found under variant '{variantName}'!");
                return(false);
            }

            Console.Write("Extracting {0} mesh(es)...", meshes.Count);

            using (var objFile = new StreamWriter(modelFile.Create()))
            {
                var objExtractor = new ObjExtractor(objFile);

                foreach (var entry in meshes)
                {
                    var meshReader = new MeshReader(CacheContext.Version, entry.Value, resourceDefinition);
                    objExtractor.ExtractMesh(meshReader, vertexCompressor, resourceStream, entry.Key);
                }

                objExtractor.Finish();
            }

            Console.WriteLine("done!");

            return(true);
        }
        public override bool Execute(List <string> args)
        {
            if (args.Count != 3)
            {
                return(false);
            }
            var variantName = args[0];
            var fileType    = args[1];
            var fileName    = args[2];

            if (fileType != "obj")
            {
                return(false);
            }

            // Find the variant to extract
            if (Definition.RenderModel == null)
            {
                Console.WriteLine("The model does not have a render model associated with it.");
                return(true);
            }
            var variant = Definition.Variants.FirstOrDefault(v => (Info.StringIds.GetString(v.Name) ?? v.Name.ToString()) == variantName);

            if (variant == null && Definition.Variants.Count > 0)
            {
                Console.WriteLine("Unable to find variant \"{0}\"", variantName);
                Console.WriteLine("Use \"listvariants\" to list available variants.");
                return(true);
            }

            // Load resource caches
            Console.WriteLine("Loading resource caches...");
            var resourceManager = new ResourceDataManager();

            try
            {
                resourceManager.LoadCachesFromDirectory(Info.CacheFile.DirectoryName);
            }
            catch
            {
                Console.WriteLine("Unable to load the resource .dat files.");
                Console.WriteLine("Make sure that they all exist and are valid.");
                return(true);
            }

            // Deserialize the render model tag
            Console.WriteLine("Reading model data...");
            RenderModel renderModel;

            using (var cacheStream = Info.CacheFile.OpenRead())
            {
                var renderModelContext = new TagSerializationContext(cacheStream, Info.Cache, Info.StringIds, Definition.RenderModel);
                renderModel = Info.Deserializer.Deserialize <RenderModel>(renderModelContext);
            }
            if (renderModel.Geometry.Resource == null)
            {
                Console.WriteLine("Render model does not have a resource associated with it");
                return(true);
            }

            // Deserialize the resource definition
            var resourceContext = new ResourceSerializationContext(renderModel.Geometry.Resource);
            var definition      = Info.Deserializer.Deserialize <RenderGeometryResourceDefinition>(resourceContext);

            using (var resourceStream = new MemoryStream())
            {
                // Extract the resource data
                resourceManager.Extract(renderModel.Geometry.Resource, resourceStream);
                using (var objFile = new StreamWriter(File.Open(fileName, FileMode.Create, FileAccess.Write)))
                {
                    var objExtractor     = new ObjExtractor(objFile);
                    var vertexCompressor = new VertexCompressor(renderModel.Geometry.Compression[0]); // Create a (de)compressor from the first compression block
                    if (variant != null)
                    {
                        // Extract each region in the variant
                        foreach (var region in variant.Regions)
                        {
                            // Get the corresonding region in the render model tag
                            if (region.RenderModelRegionIndex >= renderModel.Regions.Count)
                            {
                                continue;
                            }
                            var renderModelRegion = renderModel.Regions[region.RenderModelRegionIndex];

                            // Get the corresponding permutation in the render model tag
                            // (Just extract the first permutation for now)
                            if (region.Permutations.Count == 0)
                            {
                                continue;
                            }
                            var permutation = region.Permutations[0];
                            if (permutation.RenderModelPermutationIndex < 0 ||
                                permutation.RenderModelPermutationIndex >= renderModelRegion.Permutations.Count)
                            {
                                continue;
                            }
                            var renderModelPermutation = renderModelRegion.Permutations[permutation.RenderModelPermutationIndex];

                            // Extract each mesh in the permutation
                            var meshIndex       = renderModelPermutation.MeshIndex;
                            var meshCount       = renderModelPermutation.MeshCount;
                            var regionName      = Info.StringIds.GetString(region.Name) ?? region.Name.ToString();
                            var permutationName = Info.StringIds.GetString(permutation.Name) ?? permutation.Name.ToString();
                            Console.WriteLine("Extracting {0} mesh(es) for {1}:{2}...", meshCount, regionName, permutationName);
                            for (var i = 0; i < meshCount; i++)
                            {
                                // Create a MeshReader for the mesh and pass it to the obj extractor
                                var meshReader = new MeshReader(Info.Version, renderModel.Geometry.Meshes[meshIndex + i], definition);
                                objExtractor.ExtractMesh(meshReader, vertexCompressor, resourceStream);
                            }
                        }
                    }
                    else
                    {
                        // No variant - just extract every mesh
                        Console.WriteLine("Extracting {0} mesh(es)...", renderModel.Geometry.Meshes.Count);
                        foreach (var mesh in renderModel.Geometry.Meshes)
                        {
                            // Create a MeshReader for the mesh and pass it to the obj extractor
                            var meshReader = new MeshReader(Info.Version, mesh, definition);
                            objExtractor.ExtractMesh(meshReader, vertexCompressor, resourceStream);
                        }
                    }
                    objExtractor.Finish();
                }
            }
            Console.WriteLine("Done!");
            return(true);
        }
Example #5
0
        private void ExtractObj(FileInfo modelFile, RenderModel renderModel, Model.Variant modelVariant, RenderGeometryApiResourceDefinition resourceDefinition, Stream resourceStream)
        {
            using (var objFile = new StreamWriter(modelFile.Create()))
            {
                var objExtractor = new ObjExtractor(objFile);

                // Create a (de)compressor from the first compression block
                var vertexCompressor = new VertexCompressor(renderModel.Geometry.Compression[0]);

                if (modelVariant != null)
                {
                    // Extract each region in the variant
                    foreach (var region in modelVariant.Regions)
                    {
                        // Get the corresonding region in the render model tag
                        if (region.RenderModelRegionIndex >= renderModel.Regions.Count)
                        {
                            continue;
                        }

                        var renderModelRegion = renderModel.Regions[region.RenderModelRegionIndex];

                        // Get the corresponding permutation in the render model tag
                        // (Just extract the first permutation for now)
                        if (region.Permutations.Count == 0)
                        {
                            continue;
                        }

                        var permutation = region.Permutations[0];

                        if (permutation.RenderModelPermutationIndex < 0 ||
                            permutation.RenderModelPermutationIndex >= renderModelRegion.Permutations.Count)
                        {
                            continue;
                        }

                        var renderModelPermutation = renderModelRegion.Permutations[permutation.RenderModelPermutationIndex];

                        // Extract each mesh in the permutation
                        var meshIndex       = renderModelPermutation.MeshIndex;
                        var meshCount       = renderModelPermutation.MeshCount;
                        var regionName      = CacheContext.GetString(region.Name) ?? region.Name.ToString();
                        var permutationName = CacheContext.GetString(permutation.Name) ?? permutation.Name.ToString();

                        Console.WriteLine("Extracting {0} mesh(es) for {1}:{2}...", meshCount, regionName, permutationName);

                        for (var i = 0; i < meshCount; i++)
                        {
                            // Create a MeshReader for the mesh and pass it to the obj extractor
                            var meshReader = new MeshReader(CacheContext.Version, renderModel.Geometry.Meshes[meshIndex + i], resourceDefinition);
                            objExtractor.ExtractMesh(meshReader, vertexCompressor, resourceStream);
                        }
                    }
                }
                else
                {
                    // No variant - just extract every mesh
                    Console.WriteLine("Extracting {0} mesh(es)...", renderModel.Geometry.Meshes.Count);

                    foreach (var mesh in renderModel.Geometry.Meshes)
                    {
                        // Create a MeshReader for the mesh and pass it to the obj extractor
                        var meshReader = new MeshReader(CacheContext.Version, mesh, resourceDefinition);
                        objExtractor.ExtractMesh(meshReader, vertexCompressor, resourceStream);
                    }
                }

                objExtractor.Finish();
            }
        }
Example #6
0
        private static List <BMFVertex> ConvertGeometryVertices(VertexCompressor vertexCompressor, VertexBufferDefinition vertexBuffer, CacheVersion version, int vertexCount, int rigidNodeIndex)
        {
            var vertices = new List <BMFVertex>();

            using (var vertexDataStream = new MemoryStream(vertexBuffer.Data.Data))
            {
                var vertexStream = VertexStreamFactory.Create(version, vertexDataStream);

                for (int j = 0; j < vertexCount; j++)
                {
                    var          vertex = new BMFVertex();
                    RealVector2d texcoordTemp;

                    switch (vertexBuffer.Format)
                    {
                    case VertexBufferFormat.Rigid:
                        var rigid = vertexStream.ReadRigidVertex();

                        vertex.Position = vertexCompressor.DecompressPosition(rigid.Position).IJK;
                        texcoordTemp    = vertexCompressor.DecompressUv(rigid.Texcoord);
                        vertex.Texcoord = new RealVector3d(texcoordTemp.I, texcoordTemp.J, 0.0f);
                        vertex.Normal   = rigid.Normal;
                        vertex.Tangent  = rigid.Tangent.IJK;
                        vertex.Binormal = rigid.Binormal;

                        vertex.Weights[0] = new BMFVertexWeight {
                            NodeIndex = rigidNodeIndex, Weight = 1.0f
                        };

                        for (int i = 1; i < 4; i++)
                        {
                            vertex.Weights[i] = new BMFVertexWeight();
                        }

                        break;

                    case VertexBufferFormat.Skinned:
                        var skinned = vertexStream.ReadSkinnedVertex();

                        vertex.Position = vertexCompressor.DecompressPosition(skinned.Position).IJK;
                        texcoordTemp    = vertexCompressor.DecompressUv(skinned.Texcoord);
                        vertex.Texcoord = new RealVector3d(texcoordTemp.I, texcoordTemp.J, 0.0f);
                        vertex.Normal   = skinned.Normal;
                        vertex.Tangent  = skinned.Tangent.IJK;
                        vertex.Binormal = skinned.Binormal;

                        for (int i = 0; i < 4; i++)
                        {
                            vertex.Weights[i] = new BMFVertexWeight {
                                NodeIndex = skinned.BlendIndices[i], Weight = skinned.BlendWeights[i]
                            };
                        }
                        break;

                    default:
                        throw new InvalidOperationException("Unsupported vertex buffer type: " + vertexBuffer.Format);
                    }
                    vertices.Add(vertex);
                }
            }
            return(vertices);
        }
Example #7
0
        public bool InitGen3(GameCache cache, RenderModel mode)
        {
            Header = new BMFHeader();

            Name = cache.StringTable.GetString(mode.Name);

            Regions = new List <BMFRegion>();

            Dictionary <int, string> meshNames       = new Dictionary <int, string>();
            Dictionary <int, int>    meshRegionIndex = new Dictionary <int, int>();

            // build mesh index -> name mapping
            for (int i = 0; i < mode.Regions.Count; i++)
            {
                var region     = mode.Regions[i];
                var regionName = cache.StringTable.GetString(region.Name);
                Regions.Add(new BMFRegion {
                    Name = regionName
                });

                foreach (var permutation in region.Permutations)
                {
                    var permutationName = cache.StringTable.GetString(permutation.Name);

                    if (permutation.MeshCount > 1)
                    {
                        Console.WriteLine("Multi mesh per permutation not supported yet");
                        return(false);
                    }

                    var name = $"{permutationName}";
                    if (!meshNames.ContainsKey(permutation.MeshIndex))
                    {
                        meshNames[permutation.MeshIndex] = name;
                    }
                    else
                    {
                        Console.WriteLine("Mesh is used twice for different permutations, not supported");
                        return(false);
                    }

                    meshRegionIndex[permutation.MeshIndex] = i;
                }
            }


            // build markers
            Markers = new List <BMFMarkers>();
            foreach (var markerGroup in mode.MarkerGroups)
            {
                var groupName = cache.StringTable.GetString(markerGroup.Name);
                foreach (var marker in markerGroup.Markers)
                {
                    string name = "";
                    if (marker.RegionIndex == -1 || marker.PermutationIndex == -1)
                    {
                        name = $"#{groupName}";
                    }
                    else
                    {
                        var regionName      = cache.StringTable.GetString(mode.Regions[marker.RegionIndex].Name);
                        var permutationName = cache.StringTable.GetString(mode.Regions[marker.RegionIndex].Permutations[marker.PermutationIndex].Name);
                        name = $"#{groupName}:{regionName}:{permutationName}";
                    }

                    Markers.Add(new BMFMarkers
                    {
                        Name        = name,
                        NodeIndex   = marker.NodeIndex,
                        Translation = marker.Translation,
                        Rotation    = marker.Rotation,
                        Scale       = marker.Scale
                    });
                }
            }

            // build list of nodes
            Nodes = new List <BMFNode>();
            foreach (var node in mode.Nodes)
            {
                var geometryNode = new BMFNode
                {
                    Name                 = cache.StringTable.GetString(node.Name),
                    ParentNodeIndex      = node.ParentNode,
                    NextSiblingNodeIndex = node.NextSiblingNode,
                    FirstChildNodeIndex  = node.FirstChildNode,
                    Translation          = node.DefaultTranslation,
                    Rotation             = node.DefaultRotation,
                    Scale                = node.DefaultScale
                };
                Nodes.Add(geometryNode);
            }

            // build list of materials
            Materials = new List <BMFMaterial>();
            for (int i = 0; i < mode.Materials.Count; i++)
            {
                var    material = mode.Materials[i];
                string name     = $"material_{i}";
                if (material.RenderMethod.Name != null)
                {
                    name = material.RenderMethod.Name.Split('\\').Last();
                }

                Materials.Add(new BMFMaterial {
                    Name = name
                });
            }

            // set SH coefficients
            DefaultLighting = new BMFGlobalLighting
            {
                SHRed   = mode.SHRed,
                SHBlue  = mode.SHBlue,
                SHGreen = mode.SHGreen
            };


            LightProbes = new List <BMFLightProbe>();

            foreach (var lightProbe in mode.UnknownSHProbes)
            {
                LightProbes.Add(new BMFLightProbe
                {
                    Position     = lightProbe.Position,
                    Coefficients = lightProbe.Coefficients
                });
            }


            BoundingSpheres = mode.Geometry.BoundingSpheres;

            Meshes = new List <BMFMesh>();
            for (int i = 0; i < mode.Geometry.Meshes.Count; i++)
            {
                int vertexCount = 0;

                var mesh         = mode.Geometry.Meshes[i];
                var geometryMesh = new BMFMesh()
                {
                    Name              = meshNames[i],
                    Vertices          = new List <BMFVertex>(),
                    Faces             = new List <BMFFace>(),
                    PerVertexLighting = new List <BMFVertexLighting>(),
                    RegionIndex       = meshRegionIndex[i],
                };

                //
                // Build vertices and faces
                //


                if (mesh.ResourceIndexBuffers[0] != null)
                {
                    var indexBuffer = mesh.ResourceIndexBuffers[0];
                    using (var indexDataStream = new MemoryStream(indexBuffer.Data.Data))
                    {
                        var indexStream = new IndexBufferStream(indexDataStream, cache.Endianness);

                        foreach (var part in mesh.Parts)
                        {
                            indexStream.Position = part.FirstIndexOld;
                            ushort[] indices = new ushort[0];
                            vertexCount += part.VertexCount;

                            switch (indexBuffer.Format)
                            {
                            case IndexBufferFormat.TriangleList:
                                indices = indexStream.ReadIndices(part.IndexCountOld);
                                break;

                            case IndexBufferFormat.TriangleStrip:
                                indices = indexStream.ReadTriangleStrip(part.IndexCountOld);
                                break;

                            default:
                                throw new InvalidOperationException("Unsupported index buffer type: " + indexBuffer.Format);
                            }

                            // add faces
                            for (int j = 0; j < indices.Length; j += 3)
                            {
                                var face = new BMFFace
                                {
                                    MaterialIndex = part.MaterialIndex,
                                    Indices       = new ushort[] { indices[j], indices[j + 1], indices[j + 2] }
                                };
                                geometryMesh.Faces.Add(face);
                            }
                        }
                    }
                }
                else
                {
                    throw new Exception("No index buffer to create faces!");
                }

                if (mesh.ResourceVertexBuffers[0] != null)
                {
                    var vertexBuffer     = mesh.ResourceVertexBuffers[0];
                    var vertexCompressor = new VertexCompressor(mode.Geometry.Compression[0]);
                    geometryMesh.Vertices = ConvertGeometryVertices(vertexCompressor, vertexBuffer, cache.Version, vertexCount, mesh.RigidNodeIndex);
                }

                if (mesh.ResourceVertexBuffers[3] != null)
                {
                    var vertexBuffer = mesh.ResourceVertexBuffers[3];
                    geometryMesh.PerVertexLighting = ConvertLightingVertices(vertexBuffer, cache.Version, vertexCount);
                }

                Meshes.Add(geometryMesh);
            }

            return(true);
        }
        public override object Execute(List <string> args)
        {
            if (args.Count != 2)
            {
                return(false);
            }

            var fileType = args[0];
            var fileName = args[1];

            if (fileType != "obj")
            {
                throw new NotSupportedException(fileType);
            }

            if (Definition.Geometry2.Resource == null)
            {
                Console.WriteLine("ERROR: Render geometry does not have a resource associated with it.");
                return(true);
            }

            //
            // Deserialize the resource definition
            //

            var resourceContext = new ResourceSerializationContext(CacheContext, Definition.Geometry2.Resource);
            var definition      = CacheContext.Deserializer.Deserialize <RenderGeometryApiResourceDefinition>(resourceContext);

            using (var resourceStream = new MemoryStream())
            {
                //
                // Extract the resource data
                //

                CacheContext.ExtractResource(Definition.Geometry2.Resource, resourceStream);

                var file = new FileInfo(fileName);

                if (!file.Directory.Exists)
                {
                    file.Directory.Create();
                }

                using (var objFile = new StreamWriter(file.Create()))
                {
                    var objExtractor = new ObjExtractor(objFile);

                    foreach (var cluster in Definition.Clusters)
                    {
                        var meshReader = new MeshReader(CacheContext.Version, Definition.Geometry2.Meshes[cluster.MeshIndex], definition);
                        objExtractor.ExtractMesh(meshReader, null, resourceStream);
                    }

                    foreach (var instance in Definition.InstancedGeometryInstances)
                    {
                        var vertexCompressor = new VertexCompressor(Definition.Geometry2.Compression[0]);
                        var meshReader       = new MeshReader(CacheContext.Version, Definition.Geometry2.Meshes[instance.InstanceDefinition], definition);
                        objExtractor.ExtractMesh(meshReader, vertexCompressor, resourceStream);
                    }

                    objExtractor.Finish();
                }
            }

            Console.WriteLine("Done!");

            return(true);
        }