public override bool Execute(List<string> args) { if (args.Count != 1) return false; var outDir = args[0]; Directory.CreateDirectory(outDir); 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; } var extractor = new BitmapDdsExtractor(resourceManager); var count = 0; using (var tagsStream = _info.OpenCacheRead()) { foreach (var tag in _info.Cache.Tags.FindAllInGroup("bitm")) { Console.Write("Extracting "); TagPrinter.PrintTagShort(tag); try { var tagContext = new TagSerializationContext(tagsStream, _info.Cache, _info.StringIds, tag); var bitmap = _info.Deserializer.Deserialize<TagStructures.Bitmap>(tagContext); var ddsOutDir = outDir; if (bitmap.Images.Count > 1) { ddsOutDir = Path.Combine(outDir, tag.Index.ToString("X8")); Directory.CreateDirectory(ddsOutDir); } for (var i = 0; i < bitmap.Images.Count; i++) { var outPath = Path.Combine(ddsOutDir, ((bitmap.Images.Count > 1) ? i.ToString() : tag.Index.ToString("X8")) + ".dds"); using (var outStream = File.Open(outPath, FileMode.Create, FileAccess.Write)) { extractor.ExtractDds(_info.Deserializer, bitmap, i, outStream); } } count++; } catch (Exception ex) { Console.WriteLine("ERROR: Failed to extract bitmap: " + ex.Message); } } } Console.WriteLine("Extracted {0} bitmaps.", count); return true; }
public override bool Execute(List<string> args) { if (args.Count != 1) return false; var imagePath = args[0]; Console.WriteLine("Loading textures.dat..."); var resourceManager = new ResourceDataManager(); resourceManager.LoadCacheFromDirectory(_info.CacheFile.DirectoryName, ResourceLocation.Textures); Console.WriteLine("Importing image..."); var bitmap = new TagStructures.Bitmap { Flags = TagStructures.Bitmap.RuntimeFlags.UseResource, Sequences = new List<TagStructures.Bitmap.Sequence> { new TagStructures.Bitmap.Sequence { FirstBitmapIndex = 0, BitmapCount = 1 } }, Images = new List<TagStructures.Bitmap.Image> { new TagStructures.Bitmap.Image { Signature = new Tag("bitm").Value, Unknown28 = -1, } }, Resources = new List<TagStructures.Bitmap.BitmapResource> { new TagStructures.Bitmap.BitmapResource() } }; using (var imageStream = File.OpenRead(imagePath)) { var injector = new BitmapDdsInjector(resourceManager); injector.InjectDds(_info.Serializer, _info.Deserializer, bitmap, 0, imageStream); } Console.WriteLine("Creating a new tag..."); var tag = _info.Cache.AllocateTag(); using (var tagsStream = _info.OpenCacheReadWrite()) { var tagContext = new TagSerializationContext(tagsStream, _info.Cache, _info.StringIds, tag); _info.Serializer.Serialize(tagContext, bitmap); } Console.WriteLine(); Console.WriteLine("All done! The new bitmap tag is:"); TagPrinter.PrintTagShort(tag); return true; }
public override bool Execute(List<string> args) { if (args.Count != 2) return false; int imageIndex; if (!int.TryParse(args[0], NumberStyles.HexNumber, null, out imageIndex)) return false; if (imageIndex < 0 || imageIndex >= _bitmap.Images.Count) { Console.Error.WriteLine("Invalid image index."); return true; } var imagePath = args[1]; 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; } Console.WriteLine("Importing image data..."); try { using (var imageStream = File.OpenRead(imagePath)) { var injector = new BitmapDdsInjector(resourceManager); injector.InjectDds(_info.Serializer, _info.Deserializer, _bitmap, imageIndex, imageStream); } using (var tagsStream = _info.OpenCacheReadWrite()) { var tagContext = new TagSerializationContext(tagsStream, _info.Cache, _tag); _info.Serializer.Serialize(tagContext, _bitmap); } } catch (Exception ex) { Console.WriteLine("Importing image data failed: " + ex.Message); return true; } 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 (_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; }
public override bool Execute(List<string> args) { if (args.Count != 1) return false; var builder = new RenderModelBuilder(_info.Version); // Add a root node var node = builder.AddNode(new RenderModel.Node { Name = _stringIds.GetStringId("street_cone"), ParentNode = -1, FirstChildNode = -1, NextSiblingNode = -1, DefaultRotation = new Vector4(0, 0, 0, -1), DefaultScale = 1, InverseForward = new Vector3(1, 0, 0), InverseLeft = new Vector3(0, 1, 0), InverseUp = new Vector3(0, 0, 1), }); // Begin building the default region and permutation builder.BeginRegion(_stringIds.GetStringId("default")); builder.BeginPermutation(_stringIds.GetStringId("default")); using (var importer = new AssimpContext()) { Scene model; using (var logStream = new LogStream((msg, userData) => Console.WriteLine(msg))) { logStream.Attach(); model = importer.ImportFile(args[0], PostProcessSteps.CalculateTangentSpace | PostProcessSteps.GenerateNormals | PostProcessSteps.JoinIdenticalVertices | PostProcessSteps.SortByPrimitiveType | PostProcessSteps.PreTransformVertices | PostProcessSteps.Triangulate); logStream.Detach(); } Console.WriteLine("Assembling vertices..."); // Build a multipart mesh from the model data, // with each model mesh mapping to a part of one large mesh and having its own material builder.BeginMesh(); ushort partStartVertex = 0; ushort partStartIndex = 0; var vertices = new List<RigidVertex>(); var indices = new List<ushort>(); foreach (var mesh in model.Meshes) { for (var i = 0; i < mesh.VertexCount; i++) { var position = mesh.Vertices[i]; var normal = mesh.Normals[i]; var uv = mesh.TextureCoordinateChannels[0][i]; var tangent = mesh.Tangents[i]; var bitangent = mesh.BiTangents[i]; vertices.Add(new RigidVertex { Position = new Vector4(position.X, position.Y, position.Z, 1), Normal = new Vector3(normal.X, normal.Y, normal.Z), Texcoord = new Vector2(uv.X, uv.Y), Tangent = new Vector4(tangent.X, tangent.Y, tangent.Z, 1), Binormal = new Vector3(bitangent.X, bitangent.Y, bitangent.Z), }); } // Build the index buffer var meshIndices = mesh.GetIndices(); indices.AddRange(meshIndices.Select(i => (ushort)(i + partStartVertex))); // Define a material and part for this mesh var material = builder.AddMaterial(new RenderMaterial { RenderMethod = _cache.Tags[0x101F], }); builder.DefinePart(material, partStartIndex, (ushort)meshIndices.Length, (ushort)mesh.VertexCount); // Move to the next part partStartVertex += (ushort)mesh.VertexCount; partStartIndex += (ushort)meshIndices.Length; } // Bind the vertex and index buffers builder.BindRigidVertexBuffer(vertices, node); builder.BindIndexBuffer(indices, PrimitiveType.TriangleList); builder.EndMesh(); } builder.EndPermutation(); builder.EndRegion(); Console.WriteLine("Building Blam mesh data..."); var resourceStream = new MemoryStream(); var renderModel = builder.Build(_info.Serializer, resourceStream); Console.WriteLine("Writing resource data..."); // Add a new resource for the model data var resources = new ResourceDataManager(); resources.LoadCachesFromDirectory(_fileInfo.DirectoryName); resourceStream.Position = 0; resources.Add(renderModel.Geometry.Resource, ResourceLocation.Resources, resourceStream); Console.WriteLine("Writing tag data..."); using (var cacheStream = _fileInfo.Open(FileMode.Open, FileAccess.ReadWrite)) { var tag = _cache.Tags[0x3317]; var context = new TagSerializationContext(cacheStream, _cache, _stringIds, tag); _info.Serializer.Serialize(context, renderModel); } Console.WriteLine("Model imported successfully!"); return true; }
public override bool Execute(List<string> args) { if (args.Count != 2) return false; int imageIndex; if (!int.TryParse(args[0], NumberStyles.HexNumber, null, out imageIndex)) return false; if (imageIndex < 0 || imageIndex >= Definition.Images.Count) { Console.WriteLine("Invalid image index."); return true; } var imagePath = args[1]; 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; } Console.WriteLine("Importing image data..."); try { Definition = new Bitmap { Flags = Bitmap.RuntimeFlags.UseResource, Sequences = new List<Bitmap.Sequence> { new Bitmap.Sequence { FirstBitmapIndex = 0, BitmapCount = 1 } }, Images = new List<Bitmap.Image> { new Bitmap.Image { Signature = new Tag("bitm").Value, Unknown28 = -1 } }, Resources = new List<Bitmap.BitmapResource> { new Bitmap.BitmapResource() } }; using (var imageStream = File.OpenRead(imagePath)) { var injector = new BitmapDdsInjector(resourceManager); injector.InjectDds(Info.Serializer, Info.Deserializer, Definition, imageIndex, imageStream); } using (var tagsStream = Info.OpenCacheReadWrite()) { var tagContext = new TagSerializationContext(tagsStream, Info.Cache, Info.StringIds, Tag); Info.Serializer.Serialize(tagContext, Definition); } } catch (Exception ex) { Console.WriteLine("Importing image data failed: " + ex.Message); return true; } Console.WriteLine("Done!"); return true; }