private void CompressVertices() { var compressionInfo = BuildCompressionInfo(); var compressor = new VertexCompressor(compressionInfo); // TODO: Refactor how vertices work, this is just ugly foreach (var mesh in _meshes) { if (mesh.RigidVertices != null) { foreach (var v in mesh.RigidVertices) { v.Position = compressor.CompressPosition(v.Position); v.Texcoord = compressor.CompressUv(v.Texcoord); } } else if (mesh.SkinnedVertices != null) { foreach (var v in mesh.SkinnedVertices) { v.Position = compressor.CompressPosition(v.Position); v.Texcoord = compressor.CompressUv(v.Texcoord); } } } }
/// <summary> /// Decompresses vertex data in-place. /// </summary> /// <param name="vertices">The vertices to decompress in-place.</param> /// <param name="compressor">The compressor to use.</param> private static void DecompressVertices(IEnumerable<ObjVertex> vertices, VertexCompressor compressor) { foreach (var vertex in vertices) { vertex.Position = compressor.DecompressPosition(vertex.Position); vertex.TexCoords = compressor.DecompressUv(vertex.TexCoords); } }
/// <summary> /// Decompresses vertex data in-place. /// </summary> /// <param name="vertices">The vertices to decompress in-place.</param> /// <param name="compressor">The compressor to use.</param> public static void DecompressVertices(IEnumerable <ObjVertex> vertices, VertexCompressor compressor) { foreach (var vertex in vertices) { vertex.Position = compressor.DecompressPosition(vertex.Position); vertex.TexCoords = compressor.DecompressUv(vertex.TexCoords); } }
/// <summary> /// Writes mesh data to the .obj. /// </summary> /// <param name="reader">The mesh reader to use.</param> /// <param name="compressor">The vertex compressor to use.</param> /// <param name="resourceStream">A stream open on the resource data.</param> public void ExtractMesh(MeshReader reader, VertexCompressor compressor, Stream resourceStream) { // Read the vertex buffer and decompress each vertex var vertices = ReadVertices(reader, resourceStream); DecompressVertices(vertices, compressor); // Write out the vertices WriteVertices(vertices); // Read and write out the triangles for each part foreach (var part in reader.Mesh.Parts) { var indexes = ReadIndexes(reader, part, resourceStream); WriteTriangles(indexes); } _baseIndex += (uint)vertices.Count; }
/// <summary> /// Writes mesh data to the .obj. /// </summary> /// <param name="reader">The mesh reader to use.</param> /// <param name="compressor">The vertex compressor to use.</param> /// <param name="resourceStream">A stream open on the resource data.</param> public void ExtractMesh(MeshReader reader, VertexCompressor compressor, Stream resourceStream) { // Read the vertex buffer and decompress each vertex var vertices = ReadVertices(reader, resourceStream); DecompressVertices(vertices, compressor); // Write out the vertices WriteVertices(vertices); // Read and write out the triangles for each part foreach (var part in reader.Mesh.Parts) { var indexes = ReadIndices(reader, part, resourceStream); WriteTriangles(indexes); } _baseIndex += (uint)vertices.Count; }
public ObjMesh ReadMesh(MeshReader reader, VertexCompressor compressor, Stream resourceStream) { var vertices = ReadVertices(reader, resourceStream); if (compressor != null) { DecompressVertices(vertices, compressor); } var indices = new List <uint>(); foreach (var part in reader.Mesh.Parts) { var partIndices = ReadIndices(reader, part, resourceStream); for (var i = 0; i < partIndices.Length; i += 3) { var a = partIndices[i] + _baseIndex; var b = partIndices[i + 1] + _baseIndex; var c = partIndices[i + 2] + _baseIndex; if (a == b || a == c || b == c) { continue; } indices.AddRange(new uint[] { a, b, c }); } } _baseIndex += (uint)vertices.Count; return(new ObjMesh { Vertices = vertices, Indices = indices }); }
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 (_model.RenderModel == null) { Console.Error.WriteLine("The model does not have a render model associated with it."); return true; } var variant = _model.Variants.FirstOrDefault(v => (_stringIds.GetString(v.Name) ?? v.Name.ToString()) == variantName); if (variant == null && _model.Variants.Count > 0) { Console.Error.WriteLine("Unable to find variant \"{0}\"", variantName); Console.Error.WriteLine("Use \"listvariants\" to list available variants."); return true; } // Load resource caches Console.WriteLine("Loading resource caches..."); var resourceManager = new ResourceDataManager(); try { resourceManager.LoadCachesFromDirectory(_fileInfo.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 = _fileInfo.OpenRead()) { var renderModelContext = new TagSerializationContext(cacheStream, _cache, _model.RenderModel); renderModel = TagDeserializer.Deserialize<RenderModel>(renderModelContext); } if (renderModel.Resource == null) { Console.Error.WriteLine("Render model does not have a resource associated with it"); return true; } // Deserialize the resource definition var resourceContext = new ResourceSerializationContext(renderModel.Resource); var definition = TagDeserializer.Deserialize<RenderGeometryResourceDefinition>(resourceContext); using (var resourceStream = new MemoryStream()) { // Extract the resource data resourceManager.Extract(renderModel.Resource, resourceStream); using (var objFile = new StreamWriter(File.Open(fileName, FileMode.Create, FileAccess.Write))) { var objExtractor = new ObjExtractor(objFile); var vertexCompressor = new VertexCompressor(renderModel.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 >= 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 = _stringIds.GetString(region.Name) ?? region.Name.ToString(); var permutationName = _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(renderModel.Meshes[meshIndex + i], definition); objExtractor.ExtractMesh(meshReader, vertexCompressor, resourceStream); } } } else { // No variant - just extract every mesh Console.WriteLine("Extracting {0} mesh(es)...", renderModel.Meshes.Count); foreach (var mesh in renderModel.Meshes) { // Create a MeshReader for the mesh and pass it to the obj extractor var meshReader = new MeshReader(mesh, definition); objExtractor.ExtractMesh(meshReader, vertexCompressor, resourceStream); } } objExtractor.Finish(); } } Console.WriteLine("Done!"); return true; }