private void saveButton_Click(object sender, EventArgs e) { var sfd = new SaveFileDialog(); sfd.Filter = "MP3 Files (*.mp3)|*.mp3"; if (sfd.ShowDialog() != DialogResult.OK) { return; } if (!SoundFile.Directory.Exists) { SoundFile.Directory.Create(); } if (!SoundFile.Exists) { using (var fileStream = SoundFile.Create()) CacheContext.ExtractResource(Sound.Resource, fileStream); } var destSoundFile = new FileInfo(sfd.FileName); if (!destSoundFile.Directory.Exists) { destSoundFile.Directory.Create(); } SoundFile.CopyTo(destSoundFile.FullName); }
public override object Execute(List <string> args) { if (args.Count != 1) { return(false); } var binkFile = new FileInfo(args[0]); var resourceContext = new ResourceSerializationContext(CacheContext, Definition.Resource); var resourceDefinition = CacheContext.Deserializer.Deserialize <BinkResource>(resourceContext); using (var resourceStream = new MemoryStream()) using (var resourceReader = new BinaryReader(resourceStream)) using (var fileStream = binkFile.Create()) using (var fileWriter = new BinaryWriter(fileStream)) { CacheContext.ExtractResource(Definition.Resource, resourceStream); resourceReader.BaseStream.Position = resourceDefinition.Data.Address.Offset; fileWriter.Write(resourceReader.ReadBytes(resourceDefinition.Data.Size)); } Console.WriteLine($"Created \"{binkFile.FullName}\" successfully."); return(true); }
public override object Execute(List <string> args) { if (args.Count != 3) { return(false); } var variantName = args[0]; var fileType = args[1].ToLower(); var modelFileName = args[2]; switch (fileType) { case "obj": break; default: throw new NotImplementedException(fileType); } if (Definition.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(CacheContext, Definition.Geometry.Resource); var resourceDefinition = CacheContext.Deserializer.Deserialize <RenderGeometryApiResourceDefinition>(resourceContext); using (var resourceStream = new MemoryStream()) { // // Extract the resource data // CacheContext.ExtractResource(Definition.Geometry.Resource, resourceStream); var modelFile = new FileInfo(modelFileName); if (!modelFile.Directory.Exists) { modelFile.Directory.Create(); } switch (fileType) { case "obj": return(ExtractObj(variantName, modelFile, Definition, resourceDefinition, resourceStream)); default: throw new NotImplementedException(fileType); } } }
protected override void OnLoad(EventArgs e) { stopButton_Click(this, e); if (!SoundFile.Directory.Exists) { SoundFile.Directory.Create(); } if (SoundFile.Exists) { SoundFile.Delete(); } using (var fileStream = SoundFile.Create()) CacheContext.ExtractResource(Sound.Resource, fileStream); base.OnLoad(e); }
public override object Execute(List <string> args) { if (args.Count < 1 || args.Count > 2) { return(false); } if (args.Count == 2 && (args[0].ToLower() != "raw")) { return(false); } var file = ""; if (args.Count == 1) { file = args[0]; } else { file = args[1]; } var resourceContext = new ResourceSerializationContext(CacheContext, Geometry.Resource); var definition = CacheContext.Deserializer.Deserialize <RenderGeometryApiResourceDefinition>(resourceContext); if (args.Count == 2) { using (var edResourceStream = new MemoryStream()) using (var edResourceReader = new EndianReader(edResourceStream, EndianFormat.LittleEndian)) { var directory = args[1]; if (!Directory.Exists(directory)) { Directory.CreateDirectory(directory); } var dataOutDir = directory; for (var i = 0; i < definition.VertexBuffers.Count; i++) { edResourceStream.Position = definition.VertexBuffers[i].Definition.Data.Address.Offset; var vertexBuffer = definition.VertexBuffers[i].Definition; dataOutDir = Path.Combine(directory, $"{i}_{vertexBuffer.Format}_{vertexBuffer.Count}"); using (EndianWriter output = new EndianWriter(File.OpenWrite(dataOutDir), EndianFormat.LittleEndian)) { byte[] data = edResourceReader.ReadBytes((int)vertexBuffer.Data.Size); output.WriteBlock(data); } } } } else { // // Convert Blam data to ElDorado data // using (var fileStream = File.Create(file)) using (var fileWriter = new StreamWriter(fileStream)) { using (var edResourceStream = new MemoryStream()) using (var edResourceReader = new EndianReader(edResourceStream, EndianFormat.LittleEndian)) { // // Convert Blam vertex buffers // Console.Write("Converting vertex buffers..."); CacheContext.ExtractResource(Geometry.Resource, edResourceStream); for (var i = 0; i < definition.VertexBuffers.Count; i++) { edResourceStream.Position = definition.VertexBuffers[i].Definition.Data.Address.Offset; var vertexBuffer = definition.VertexBuffers[i].Definition; //fileWriter.WriteLine($"Offset = {vertexBuffer.Data.Address.Offset.ToString("X8")} Count = {vertexBuffer.Count} Size = {vertexBuffer.VertexSize}, Format = {vertexBuffer.Format.ToString()}"); //fileWriter.WriteLine(Environment.NewLine); //fileWriter.WriteLine($"Vertex buffer index: {i}"); switch (vertexBuffer.Format) { case VertexBufferFormat.TinyPosition: for (var j = 0; j < vertexBuffer.Count; j++) { fileWriter.WriteLine($"Position = ({edResourceReader.ReadUInt16().ToString("X4")},{edResourceReader.ReadUInt16().ToString("X4")},{edResourceReader.ReadUInt16().ToString("X4")},{edResourceReader.ReadUInt16().ToString("X4")})"); fileWriter.WriteLine($"Normal = ({edResourceReader.ReadByte().ToString("X2")},{edResourceReader.ReadByte().ToString("X2")},{edResourceReader.ReadByte().ToString("X2")},{edResourceReader.ReadByte().ToString("X2")})"); fileWriter.WriteLine($"Color = {edResourceReader.ReadUInt32().ToString("X8")}"); } break; case VertexBufferFormat.StaticPerVertex: for (var j = 0; j < vertexBuffer.Count; j++) { fileWriter.WriteLine($"{vertexBuffer.Format} index: {j}:"); fileWriter.WriteLine($"Texcoord = " + edResourceReader.ReadUInt32().ToString("X8")); fileWriter.WriteLine($"Texcoord = " + edResourceReader.ReadUInt32().ToString("X8")); fileWriter.WriteLine($"Texcoord = " + edResourceReader.ReadUInt32().ToString("X8")); fileWriter.WriteLine($"Texcoord = " + edResourceReader.ReadUInt32().ToString("X8")); fileWriter.WriteLine($"Texcoord = " + edResourceReader.ReadUInt32().ToString("X8")); fileWriter.WriteLine($"End of {vertexBuffer.Format} index: {j}"); fileWriter.WriteLine(Environment.NewLine); } break; case VertexBufferFormat.Skinned: for (var j = 0; j < vertexBuffer.Count; j++) { fileWriter.WriteLine($"{j}:"); fileWriter.WriteLine($"Position X = " + edResourceReader.ReadSingle() + " Y = " + edResourceReader.ReadSingle() + " Z = " + edResourceReader.ReadSingle()); fileWriter.WriteLine($"Texcoord U = " + edResourceReader.ReadSingle() + " V = " + edResourceReader.ReadSingle()); fileWriter.WriteLine($"Normal X = " + edResourceReader.ReadSingle() + " Y = " + edResourceReader.ReadSingle() + " Z = " + edResourceReader.ReadSingle()); fileWriter.WriteLine($"Tangent X = " + edResourceReader.ReadSingle() + " Y = " + edResourceReader.ReadSingle() + " Z = " + edResourceReader.ReadSingle()); fileWriter.WriteLine($"Binormal X = " + edResourceReader.ReadSingle() + " Y = " + edResourceReader.ReadSingle() + " Z = " + edResourceReader.ReadSingle()); edResourceReader.ReadUInt32(); edResourceReader.ReadUInt32(); } break; /* * case VertexBufferFormat.Unknown1B: * var goodCount = 0; * for (var j = 0; j < vertexBuffer.Count; j++) * { * //fileWriter.WriteLine($"Index: {j}:"); * string values = $"({ edResourceReader.ReadSingle()},{ edResourceReader.ReadSingle()}," + * $"{edResourceReader.ReadSingle()},{edResourceReader.ReadSingle()},{edResourceReader.ReadSingle()},{edResourceReader.ReadSingle()}" + * $",{edResourceReader.ReadSingle()},{edResourceReader.ReadSingle()},{edResourceReader.ReadSingle()})"; * if(values != "(0,0,0,0,0,0,0,0,0)") * { * goodCount++; * //fileWriter.WriteLine($"(1,2,3,4,5,6,7,8,9) = "+values); * } * * * /* * fileWriter.WriteLine($"Unknown 1 = " + edResourceReader.ReadSingle()); * fileWriter.WriteLine($"Unknown 2 = " + edResourceReader.ReadSingle()); * fileWriter.WriteLine($"Unknown 3 = " + edResourceReader.ReadSingle()); * fileWriter.WriteLine($"Unknown 4 = " + edResourceReader.ReadSingle()); * fileWriter.WriteLine($"Unknown 5 = " + edResourceReader.ReadSingle()); * fileWriter.WriteLine($"Unknown 6 = " + edResourceReader.ReadSingle()); * fileWriter.WriteLine($"Unknown 7 = " + edResourceReader.ReadSingle()); * fileWriter.WriteLine($"Unknown 8 = " + edResourceReader.ReadSingle()); * fileWriter.WriteLine($"Unknown 9 = " + edResourceReader.ReadSingle()); * * } * //fileWriter.WriteLine($"Valid Unknown1B count = {goodCount}"); * break; * * case VertexBufferFormat.Unknown1A: * for (var j = 0; j < vertexBuffer.Count; j++) * { * //fileWriter.WriteLine($"Index: {j}:"); * //fileWriter.WriteLine($"Unknown 1 = " + edResourceReader.ReadUInt32().ToString("X8")); * fileWriter.WriteLine($"(1,2,3) = ({edResourceReader.ReadUInt32().ToString("X8")},{edResourceReader.ReadUInt32().ToString("X8")},{edResourceReader.ReadUInt32().ToString("X8")})"); * } * break; * * case VertexBufferFormat.Rigid: * for (var j = 0; j < vertexBuffer.Count; j++) * { * fileWriter.WriteLine($"{j}:"); * fileWriter.WriteLine($"Position X = " + edResourceReader.ReadSingle() + " Y = " + edResourceReader.ReadSingle() + " Z = " + edResourceReader.ReadSingle()); * fileWriter.WriteLine($"Texcoord U = " + edResourceReader.ReadSingle() + " V = " + edResourceReader.ReadSingle()); * fileWriter.WriteLine($"Normal X = " + edResourceReader.ReadSingle() + " Y = " + edResourceReader.ReadSingle() + " Z = " + edResourceReader.ReadSingle()); * fileWriter.WriteLine($"Tangent X = " + edResourceReader.ReadSingle() + " Y = " + edResourceReader.ReadSingle() + " Z = " + edResourceReader.ReadSingle()); * fileWriter.WriteLine($"Binormal X = " + edResourceReader.ReadSingle() + " Y = " + edResourceReader.ReadSingle() + " Z = " + edResourceReader.ReadSingle()); * } * break; * * case VertexBufferFormat.StaticPerPixel: * for (var j = 0; j < vertexBuffer.Count; j++) * { * fileWriter.WriteLine($"{j} U = " + edResourceReader.ReadSingle() + " V = " + edResourceReader.ReadSingle()); * //fileWriter.WriteLine(Environment.NewLine); * } * break; * * case VertexBufferFormat.AmbientPrt: * for (var j = 0; j < vertexBuffer.Count; j++) * { * fileWriter.WriteLine($"{j} Blend weight = " + edResourceReader.ReadSingle()); * //fileWriter.WriteLine(Environment.NewLine); * } * break; * * * case VertexBufferFormat.World: * for (var j = 0; j < vertexBuffer.Count; j++) * { * fileWriter.WriteLine($"{j}:"); * fileWriter.WriteLine($"Position X = " + edResourceReader.ReadSingle() + " Y = " + edResourceReader.ReadSingle() + " Z = " + edResourceReader.ReadSingle()); * fileWriter.WriteLine($"Texcoord U = " + edResourceReader.ReadSingle() + " V = " + edResourceReader.ReadSingle()); * fileWriter.WriteLine($"Normal X = " + edResourceReader.ReadSingle() + " Y = " + edResourceReader.ReadSingle() + " Z = " + edResourceReader.ReadSingle()); * fileWriter.WriteLine($"Tangent X = " + edResourceReader.ReadSingle() + " Y = " + edResourceReader.ReadSingle() + " Z = " + edResourceReader.ReadSingle()); * fileWriter.WriteLine($"Binormal X = " + edResourceReader.ReadSingle() + " Y = " + edResourceReader.ReadSingle() + " Z = " + edResourceReader.ReadSingle()); * } * break; * * * */ /* * case VertexBufferFormat.QuadraticPrt: * for (var j = 0; j < vertexBuffer.Count; j++) * { * fileWriter.WriteLine($"{vertexBuffer.Format} index: {j}:"); * fileWriter.WriteLine($"A X = " + edResourceReader.ReadSingle() + " Y = " + edResourceReader.ReadSingle() + " Z = " + edResourceReader.ReadSingle()); * fileWriter.WriteLine($"B X = " + edResourceReader.ReadSingle() + " Y = " + edResourceReader.ReadSingle() + " Z = " + edResourceReader.ReadSingle()); * fileWriter.WriteLine($"C X = " + edResourceReader.ReadSingle() + " Y = " + edResourceReader.ReadSingle() + " Z = " + edResourceReader.ReadSingle()); * fileWriter.WriteLine($"End of {vertexBuffer.Format} index: {j}"); * fileWriter.WriteLine(Environment.NewLine); * } * break; * * * * case VertexBufferFormat.Unknown1B: * for (var j = 0; j < vertexBuffer.Count; j++) * { * fileWriter.WriteLine($"{vertexBuffer.Format} index: {j}:"); * fileWriter.WriteLine($"Unknown 1 = " + edResourceReader.ReadSingle()); * fileWriter.WriteLine($"Unknown 2 = " + edResourceReader.ReadSingle()); * fileWriter.WriteLine($"Unknown 3 = " + edResourceReader.ReadSingle()); * fileWriter.WriteLine($"Unknown 4 = " + edResourceReader.ReadSingle()); * fileWriter.WriteLine($"Unknown 5 = " + edResourceReader.ReadSingle()); * fileWriter.WriteLine($"Unknown 6 = " + edResourceReader.ReadSingle()); * fileWriter.WriteLine($"Unknown 7 = " + edResourceReader.ReadSingle()); * fileWriter.WriteLine($"Unknown 8 = " + edResourceReader.ReadSingle()); * fileWriter.WriteLine($"Unknown 9 = " + edResourceReader.ReadSingle()); * fileWriter.WriteLine($"End of {vertexBuffer.Format} index: {j}"); * fileWriter.WriteLine(Environment.NewLine); * } * break; * * case VertexBufferFormat.Decorator: * for (var j = 0; j < vertexBuffer.Count; j++) * { * fileWriter.WriteLine($"{vertexBuffer.Format} index: {j}:"); * fileWriter.WriteLine($"Position X = " + edResourceReader.ReadSingle() + " Y = " + edResourceReader.ReadSingle() + " Z = " + edResourceReader.ReadSingle()); * fileWriter.WriteLine($"Texcoord U = " + edResourceReader.ReadSingle() + " V = " + edResourceReader.ReadSingle()); * fileWriter.WriteLine($"Normal X = " + edResourceReader.ReadSingle() + " Y = " + edResourceReader.ReadSingle() + " Z = " + edResourceReader.ReadSingle()); * fileWriter.WriteLine($"End of {vertexBuffer.Format} index: {j}"); * fileWriter.WriteLine(Environment.NewLine); * } * break; * * case VertexBufferFormat.LinearPrt: * for (var j = 0; j < vertexBuffer.Count; j++) * { * fileWriter.WriteLine($"{vertexBuffer.Format} index: {j}:"); * fileWriter.WriteLine($"Hex : " + edResourceReader.ReadUInt32().ToString("X8")); * fileWriter.WriteLine($"End of {vertexBuffer.Format} index: {j}"); * fileWriter.WriteLine(Environment.NewLine); * } * break; */ } //fileWriter.WriteLine($"End of Vertex Buffer index: {i}"); //fileWriter.WriteLine(Environment.NewLine); } } } } return(true); }
public override object Execute(List <string> args) { if (args.Count != 1) { return(false); } if (Definition.CollisionBspResource == null) { Console.WriteLine("ERROR: Collision geometry does not have a resource associated with it."); return(true); } var resourceContext = new ResourceSerializationContext(CacheContext, Definition.CollisionBspResource); var resourceDefinition = CacheContext.Deserializer.Deserialize <StructureBspTagResources>(resourceContext); using (var resourceStream = new MemoryStream()) { CacheContext.ExtractResource(Definition.CollisionBspResource, resourceStream); using (var reader = new EndianReader(resourceStream)) { foreach (var cbsp in resourceDefinition.CollisionBsps) { reader.BaseStream.Position = cbsp.Bsp3dNodes.Address.Offset; for (var i = 0; i < cbsp.Bsp3dNodes.Count; i++) { var element = CacheContext.Deserializer.DeserializeValue(reader, null, null, typeof(CollisionGeometry.Bsp3dNode)); cbsp.Bsp3dNodes.Add((CollisionGeometry.Bsp3dNode)element); } reader.BaseStream.Position = cbsp.Planes.Address.Offset; for (var i = 0; i < cbsp.Planes.Count; i++) { var element = CacheContext.Deserializer.DeserializeValue(reader, null, null, typeof(CollisionGeometry.Plane)); cbsp.Planes.Add((CollisionGeometry.Plane)element); } reader.BaseStream.Position = cbsp.Leaves.Address.Offset; for (var i = 0; i < cbsp.Leaves.Count; i++) { var element = CacheContext.Deserializer.DeserializeValue(reader, null, null, typeof(CollisionGeometry.Leaf)); cbsp.Leaves.Add((CollisionGeometry.Leaf)element); } reader.BaseStream.Position = cbsp.Bsp2dReferences.Address.Offset; for (var i = 0; i < cbsp.Bsp2dReferences.Count; i++) { var element = CacheContext.Deserializer.DeserializeValue(reader, null, null, typeof(CollisionGeometry.Bsp2dReference)); cbsp.Bsp2dReferences.Add((CollisionGeometry.Bsp2dReference)element); } reader.BaseStream.Position = cbsp.Bsp2dNodes.Address.Offset; for (var i = 0; i < cbsp.Bsp2dNodes.Count; i++) { var element = CacheContext.Deserializer.DeserializeValue(reader, null, null, typeof(CollisionGeometry.Bsp2dNode)); cbsp.Bsp2dNodes.Add((CollisionGeometry.Bsp2dNode)element); } reader.BaseStream.Position = cbsp.Surfaces.Address.Offset; for (var i = 0; i < cbsp.Surfaces.Count; i++) { var element = CacheContext.Deserializer.DeserializeValue(reader, null, null, typeof(CollisionGeometry.Surface)); cbsp.Surfaces.Add((CollisionGeometry.Surface)element); } reader.BaseStream.Position = cbsp.Edges.Address.Offset; for (var i = 0; i < cbsp.Edges.Count; i++) { var element = CacheContext.Deserializer.DeserializeValue(reader, null, null, typeof(CollisionGeometry.Edge)); cbsp.Edges.Add((CollisionGeometry.Edge)element); } reader.BaseStream.Position = cbsp.Vertices.Address.Offset; for (var i = 0; i < cbsp.Vertices.Count; i++) { var element = CacheContext.Deserializer.DeserializeValue(reader, null, null, typeof(CollisionGeometry.Vertex)); cbsp.Vertices.Add((CollisionGeometry.Vertex)element); } } foreach (var cbsp in resourceDefinition.LargeCollisionBsps) { reader.BaseStream.Position = cbsp.Bsp3dNodes.Address.Offset; for (var i = 0; i < cbsp.Bsp3dNodes.Count; i++) { var element = CacheContext.Deserializer.DeserializeValue(reader, null, null, typeof(StructureBspTagResources.LargeCollisionBspBlock.Bsp3dNode)); cbsp.Bsp3dNodes.Add((StructureBspTagResources.LargeCollisionBspBlock.Bsp3dNode)element); } reader.BaseStream.Position = cbsp.Planes.Address.Offset; for (var i = 0; i < cbsp.Planes.Count; i++) { var element = CacheContext.Deserializer.DeserializeValue(reader, null, null, typeof(CollisionGeometry.Plane)); cbsp.Planes.Add((CollisionGeometry.Plane)element); } reader.BaseStream.Position = cbsp.Leaves.Address.Offset; for (var i = 0; i < cbsp.Leaves.Count; i++) { var element = CacheContext.Deserializer.DeserializeValue(reader, null, null, typeof(CollisionGeometry.Leaf)); cbsp.Leaves.Add((CollisionGeometry.Leaf)element); } reader.BaseStream.Position = cbsp.Bsp2dReferences.Address.Offset; for (var i = 0; i < cbsp.Bsp2dReferences.Count; i++) { var element = CacheContext.Deserializer.DeserializeValue(reader, null, null, typeof(StructureBspTagResources.LargeCollisionBspBlock.Bsp2dReference)); cbsp.Bsp2dReferences.Add((StructureBspTagResources.LargeCollisionBspBlock.Bsp2dReference)element); } reader.BaseStream.Position = cbsp.Bsp2dNodes.Address.Offset; for (var i = 0; i < cbsp.Bsp2dNodes.Count; i++) { var element = CacheContext.Deserializer.DeserializeValue(reader, null, null, typeof(StructureBspTagResources.LargeCollisionBspBlock.Bsp2dNode)); cbsp.Bsp2dNodes.Add((StructureBspTagResources.LargeCollisionBspBlock.Bsp2dNode)element); } reader.BaseStream.Position = cbsp.Surfaces.Address.Offset; for (var i = 0; i < cbsp.Surfaces.Count; i++) { var element = CacheContext.Deserializer.DeserializeValue(reader, null, null, typeof(StructureBspTagResources.LargeCollisionBspBlock.Surface)); cbsp.Surfaces.Add((StructureBspTagResources.LargeCollisionBspBlock.Surface)element); } reader.BaseStream.Position = cbsp.Edges.Address.Offset; for (var i = 0; i < cbsp.Edges.Count; i++) { var element = CacheContext.Deserializer.DeserializeValue(reader, null, null, typeof(StructureBspTagResources.LargeCollisionBspBlock.Edge)); cbsp.Edges.Add((StructureBspTagResources.LargeCollisionBspBlock.Edge)element); } reader.BaseStream.Position = cbsp.Vertices.Address.Offset; for (var i = 0; i < cbsp.Vertices.Count; i++) { var element = CacheContext.Deserializer.DeserializeValue(reader, null, null, typeof(StructureBspTagResources.LargeCollisionBspBlock.Vertex)); cbsp.Vertices.Add((StructureBspTagResources.LargeCollisionBspBlock.Vertex)element); } } foreach (var instance in resourceDefinition.InstancedGeometry) { reader.BaseStream.Position = instance.CollisionInfo.Bsp3dNodes.Address.Offset; for (var i = 0; i < instance.CollisionInfo.Bsp3dNodes.Count; i++) { var element = CacheContext.Deserializer.DeserializeValue(reader, null, null, typeof(CollisionGeometry.Bsp3dNode)); instance.CollisionInfo.Bsp3dNodes.Add((CollisionGeometry.Bsp3dNode)element); } reader.BaseStream.Position = instance.CollisionInfo.Planes.Address.Offset; for (var i = 0; i < instance.CollisionInfo.Planes.Count; i++) { var element = CacheContext.Deserializer.DeserializeValue(reader, null, null, typeof(CollisionGeometry.Plane)); instance.CollisionInfo.Planes.Add((CollisionGeometry.Plane)element); } reader.BaseStream.Position = instance.CollisionInfo.Leaves.Address.Offset; for (var i = 0; i < instance.CollisionInfo.Leaves.Count; i++) { var element = CacheContext.Deserializer.DeserializeValue(reader, null, null, typeof(CollisionGeometry.Leaf)); instance.CollisionInfo.Leaves.Add((CollisionGeometry.Leaf)element); } reader.BaseStream.Position = instance.CollisionInfo.Bsp2dReferences.Address.Offset; for (var i = 0; i < instance.CollisionInfo.Bsp2dReferences.Count; i++) { var element = CacheContext.Deserializer.DeserializeValue(reader, null, null, typeof(CollisionGeometry.Bsp2dReference)); instance.CollisionInfo.Bsp2dReferences.Add((CollisionGeometry.Bsp2dReference)element); } reader.BaseStream.Position = instance.CollisionInfo.Bsp2dNodes.Address.Offset; for (var i = 0; i < instance.CollisionInfo.Bsp2dNodes.Count; i++) { var element = CacheContext.Deserializer.DeserializeValue(reader, null, null, typeof(CollisionGeometry.Bsp2dNode)); instance.CollisionInfo.Bsp2dNodes.Add((CollisionGeometry.Bsp2dNode)element); } reader.BaseStream.Position = instance.CollisionInfo.Surfaces.Address.Offset; for (var i = 0; i < instance.CollisionInfo.Surfaces.Count; i++) { var element = CacheContext.Deserializer.DeserializeValue(reader, null, null, typeof(CollisionGeometry.Surface)); instance.CollisionInfo.Surfaces.Add((CollisionGeometry.Surface)element); } reader.BaseStream.Position = instance.CollisionInfo.Edges.Address.Offset; for (var i = 0; i < instance.CollisionInfo.Edges.Count; i++) { var element = CacheContext.Deserializer.DeserializeValue(reader, null, null, typeof(CollisionGeometry.Edge)); instance.CollisionInfo.Edges.Add((CollisionGeometry.Edge)element); } reader.BaseStream.Position = instance.CollisionInfo.Vertices.Address.Offset; for (var i = 0; i < instance.CollisionInfo.Vertices.Count; i++) { var element = CacheContext.Deserializer.DeserializeValue(reader, null, null, typeof(CollisionGeometry.Vertex)); instance.CollisionInfo.Vertices.Add((CollisionGeometry.Vertex)element); } foreach (var cbsp in instance.CollisionGeometries) { reader.BaseStream.Position = cbsp.Bsp3dNodes.Address.Offset; for (var i = 0; i < cbsp.Bsp3dNodes.Count; i++) { var element = CacheContext.Deserializer.DeserializeValue(reader, null, null, typeof(CollisionGeometry.Bsp3dNode)); cbsp.Bsp3dNodes.Add((CollisionGeometry.Bsp3dNode)element); } reader.BaseStream.Position = cbsp.Planes.Address.Offset; for (var i = 0; i < cbsp.Planes.Count; i++) { var element = CacheContext.Deserializer.DeserializeValue(reader, null, null, typeof(CollisionGeometry.Plane)); cbsp.Planes.Add((CollisionGeometry.Plane)element); } reader.BaseStream.Position = cbsp.Leaves.Address.Offset; for (var i = 0; i < cbsp.Leaves.Count; i++) { var element = CacheContext.Deserializer.DeserializeValue(reader, null, null, typeof(CollisionGeometry.Leaf)); cbsp.Leaves.Add((CollisionGeometry.Leaf)element); } reader.BaseStream.Position = cbsp.Bsp2dReferences.Address.Offset; for (var i = 0; i < cbsp.Bsp2dReferences.Count; i++) { var element = CacheContext.Deserializer.DeserializeValue(reader, null, null, typeof(CollisionGeometry.Bsp2dReference)); cbsp.Bsp2dReferences.Add((CollisionGeometry.Bsp2dReference)element); } reader.BaseStream.Position = cbsp.Bsp2dNodes.Address.Offset; for (var i = 0; i < cbsp.Bsp2dNodes.Count; i++) { var element = CacheContext.Deserializer.DeserializeValue(reader, null, null, typeof(CollisionGeometry.Bsp2dNode)); cbsp.Bsp2dNodes.Add((CollisionGeometry.Bsp2dNode)element); } reader.BaseStream.Position = cbsp.Surfaces.Address.Offset; for (var i = 0; i < cbsp.Surfaces.Count; i++) { var element = CacheContext.Deserializer.DeserializeValue(reader, null, null, typeof(CollisionGeometry.Surface)); cbsp.Surfaces.Add((CollisionGeometry.Surface)element); } reader.BaseStream.Position = cbsp.Edges.Address.Offset; for (var i = 0; i < cbsp.Edges.Count; i++) { var element = CacheContext.Deserializer.DeserializeValue(reader, null, null, typeof(CollisionGeometry.Edge)); cbsp.Edges.Add((CollisionGeometry.Edge)element); } reader.BaseStream.Position = cbsp.Vertices.Address.Offset; for (var i = 0; i < cbsp.Vertices.Count; i++) { var element = CacheContext.Deserializer.DeserializeValue(reader, null, null, typeof(CollisionGeometry.Vertex)); cbsp.Vertices.Add((CollisionGeometry.Vertex)element); } } for (var i = 0; i < instance.Unknown1.Count; i++) { var element = CacheContext.Deserializer.DeserializeValue(reader, null, null, typeof(StructureBspTagResources.InstancedGeometryBlock.Unknown1Block)); instance.Unknown1.Add((StructureBspTagResources.InstancedGeometryBlock.Unknown1Block)element); } for (var i = 0; i < instance.Unknown2.Count; i++) { var element = CacheContext.Deserializer.DeserializeValue(reader, null, null, typeof(StructureBspTagResources.InstancedGeometryBlock.Unknown2Block)); instance.Unknown2.Add((StructureBspTagResources.InstancedGeometryBlock.Unknown2Block)element); } for (var i = 0; i < instance.Unknown3.Count; i++) { var element = CacheContext.Deserializer.DeserializeValue(reader, null, null, typeof(StructureBspTagResources.InstancedGeometryBlock.Unknown3Block)); instance.Unknown3.Add((StructureBspTagResources.InstancedGeometryBlock.Unknown3Block)element); } foreach (var collision in instance.BspPhysics) { for (var i = 0; i < collision.Data.Count; i++) { var element = CacheContext.Deserializer.DeserializeValue(reader, null, null, typeof(byte)); collision.Data.Add(new StructureBspTagResources.CollisionBspPhysicsBlock.Datum { Value = (byte)element }); } } } } var file = new FileInfo(args[0]); if (!file.Directory.Exists) { file.Directory.Create(); } using (var writer = new StreamWriter(file.Create())) { var baseVertex = 0; foreach (var bsp in resourceDefinition.CollisionBsps) { for (var i = 0; i < bsp.Vertices.Count; i++) { var vertex = bsp.Vertices[i]; writer.WriteLine($"v {vertex.Point.X} {vertex.Point.Z} {vertex.Point.Y}"); } writer.WriteLine($"g bsp_surfaces_{resourceDefinition.CollisionBsps.IndexOf(bsp)}"); for (var i = 0; i < bsp.Surfaces.Count; i++) { var surface = bsp.Surfaces[i]; var vertices = new HashSet <short>(); var edge = bsp.Edges[surface.FirstEdge]; writer.Write("f"); while (true) { if (edge.LeftSurface == i) { writer.Write($" {baseVertex + edge.StartVertex + 1}"); if (edge.ForwardEdge == surface.FirstEdge) { break; } else { edge = bsp.Edges[edge.ForwardEdge]; } } else if (edge.RightSurface == i) { writer.Write($" {baseVertex + edge.EndVertex + 1}"); if (edge.ReverseEdge == surface.FirstEdge) { break; } else { edge = bsp.Edges[edge.ReverseEdge]; } } } writer.WriteLine(); } baseVertex += bsp.Vertices.Count; } foreach (var largeBsp in resourceDefinition.LargeCollisionBsps) { for (var i = 0; i < largeBsp.Vertices.Count; i++) { var vertex = largeBsp.Vertices[i]; writer.WriteLine($"v {vertex.Point.X} {vertex.Point.Z} {vertex.Point.Y}"); } writer.WriteLine($"g large_bsp_surfaces_{resourceDefinition.LargeCollisionBsps.IndexOf(largeBsp)}"); for (var i = 0; i < largeBsp.Surfaces.Count; i++) { var surface = largeBsp.Surfaces[i]; var vertices = new HashSet <short>(); var edge = largeBsp.Edges[surface.FirstEdge]; writer.Write("f"); while (true) { if (edge.LeftSurface == i) { writer.Write($" {baseVertex + edge.StartVertex + 1}"); if (edge.ForwardEdge == surface.FirstEdge) { break; } else { edge = largeBsp.Edges[edge.ForwardEdge]; } } else if (edge.RightSurface == i) { writer.Write($" {baseVertex + edge.EndVertex + 1}"); if (edge.ReverseEdge == surface.FirstEdge) { break; } else { edge = largeBsp.Edges[edge.ReverseEdge]; } } } writer.WriteLine(); } baseVertex += largeBsp.Vertices.Count; } foreach (var instanceDef in Definition.InstancedGeometryInstances) { if (instanceDef.InstanceDefinition == -1) { continue; } var instance = resourceDefinition.InstancedGeometry[instanceDef.InstanceDefinition]; var instanceName = instanceDef.Name != StringId.Invalid ? CacheContext.GetString(instanceDef.Name) : $"instance_{instanceDef.InstanceDefinition}"; for (var i = 0; i < instance.CollisionInfo.Vertices.Count; i++) { var vertex = instance.CollisionInfo.Vertices[i]; var point = Vector3.Transform( new Vector3(vertex.Point.X, vertex.Point.Y, vertex.Point.Z), new Matrix4x4( instanceDef.Matrix.m11, instanceDef.Matrix.m12, instanceDef.Matrix.m13, 0.0f, instanceDef.Matrix.m21, instanceDef.Matrix.m22, instanceDef.Matrix.m23, 0.0f, instanceDef.Matrix.m31, instanceDef.Matrix.m32, instanceDef.Matrix.m33, 0.0f, instanceDef.Matrix.m41, instanceDef.Matrix.m42, instanceDef.Matrix.m43, 0.0f)); writer.WriteLine($"v {point.X} {point.Z} {point.Y}"); } writer.WriteLine($"g {instanceName}_main_surfaces"); for (var i = 0; i < instance.CollisionInfo.Surfaces.Count; i++) { var surface = instance.CollisionInfo.Surfaces[i]; var vertices = new HashSet <short>(); var edge = instance.CollisionInfo.Edges[surface.FirstEdge]; writer.Write("f"); while (true) { if (edge.LeftSurface == i) { writer.Write($" {baseVertex + edge.StartVertex + 1}"); if (edge.ForwardEdge == surface.FirstEdge) { break; } else { edge = instance.CollisionInfo.Edges[edge.ForwardEdge]; } } else if (edge.RightSurface == i) { writer.Write($" {baseVertex + edge.EndVertex + 1}"); if (edge.ReverseEdge == surface.FirstEdge) { break; } else { edge = instance.CollisionInfo.Edges[edge.ReverseEdge]; } } } writer.WriteLine(); } baseVertex += instance.CollisionInfo.Vertices.Count; foreach (var bsp in instance.CollisionGeometries) { for (var i = 0; i < bsp.Vertices.Count; i++) { var vertex = bsp.Vertices[i]; writer.WriteLine($"v {vertex.Point.X} {vertex.Point.Z} {vertex.Point.Y}"); } writer.WriteLine($"g {instanceName}_bsp_surfaces_{resourceDefinition.CollisionBsps.IndexOf(bsp)}"); for (var i = 0; i < bsp.Surfaces.Count; i++) { var surface = bsp.Surfaces[i]; var vertices = new HashSet <short>(); var edge = bsp.Edges[surface.FirstEdge]; writer.Write("f"); while (true) { if (edge.LeftSurface == i) { writer.Write($" {baseVertex + edge.StartVertex + 1}"); if (edge.ForwardEdge == surface.FirstEdge) { break; } else { edge = bsp.Edges[edge.ForwardEdge]; } } else if (edge.RightSurface == i) { writer.Write($" {baseVertex + edge.EndVertex + 1}"); if (edge.ReverseEdge == surface.FirstEdge) { break; } else { edge = bsp.Edges[edge.ReverseEdge]; } } } writer.WriteLine(); } baseVertex += bsp.Vertices.Count; } } } } return(true); }
public override object Execute(List <string> args) { if (Definition.PathfindingResource == null) { Console.WriteLine("ERROR: Pathfinding geometry does not have a resource associated with it."); return(true); } var resourceContext = new ResourceSerializationContext(CacheContext, Definition.PathfindingResource); var resourceDefinition = CacheContext.Deserializer.Deserialize <StructureBspCacheFileTagResources>(resourceContext); using (var resourceStream = new MemoryStream()) using (var reader = new EndianReader(resourceStream)) using (var writer = new EndianWriter(resourceStream)) { CacheContext.ExtractResource(Definition.PathfindingResource, resourceStream); var dataContext = new DataSerializationContext(reader, writer); foreach (var pathfindingDatum in resourceDefinition.PathfindingData) { resourceStream.Position = pathfindingDatum.Sectors.Address.Offset; for (var i = 0; i < pathfindingDatum.Sectors.Count; i++) { pathfindingDatum.Sectors.Add( CacheContext.Deserializer.Deserialize <ScenarioStructureBsp.PathfindingDatum.Sector>(dataContext)); } resourceStream.Position = pathfindingDatum.Links.Address.Offset; for (var i = 0; i < pathfindingDatum.Links.Count; i++) { pathfindingDatum.Links.Add( CacheContext.Deserializer.Deserialize <ScenarioStructureBsp.PathfindingDatum.Link>(dataContext)); } resourceStream.Position = pathfindingDatum.PathfindingHints.Address.Offset; for (var i = 0; i < pathfindingDatum.PathfindingHints.Count; i++) { pathfindingDatum.PathfindingHints.Add( CacheContext.Deserializer.Deserialize <ScenarioStructureBsp.PathfindingDatum.PathfindingHint>(dataContext)); } resourceStream.Position = pathfindingDatum.Vertices.Address.Offset; for (var i = 0; i < pathfindingDatum.Vertices.Count; i++) { pathfindingDatum.Vertices.Add( CacheContext.Deserializer.Deserialize <ScenarioStructureBsp.PathfindingDatum.Vertex>(dataContext)); } for (var i = 0; i < pathfindingDatum.PathfindingHints.Count; i++) { var hint = pathfindingDatum.PathfindingHints[i]; if (hint.HintType != JumpLink && hint.HintType != WallJumpLink) { continue; } var hintverts = new List <short>(); var success = false; hintverts.Add((short)(hint.Data[1] & ushort.MaxValue)); hintverts.Add((short)((hint.Data[1] >> 16) & ushort.MaxValue)); if (hintverts[0] == -1 || hintverts[1] == -1) { continue; } float hint_x = (pathfindingDatum.Vertices[hintverts[0]].Position.X + pathfindingDatum.Vertices[hintverts[1]].Position.X) / 2.0f; float hint_y = (pathfindingDatum.Vertices[hintverts[0]].Position.Y + pathfindingDatum.Vertices[hintverts[1]].Position.Y) / 2.0f; float hint_z = (pathfindingDatum.Vertices[hintverts[0]].Position.Z + pathfindingDatum.Vertices[hintverts[1]].Position.Z) / 2.0f; var sectorlist = new List <int>(); var backupsectorlist = new List <int>(); var zavelist = new List <float>(); var backupzavelist = new List <float>(); for (var s = 0; s < pathfindingDatum.Sectors.Count; s++) { var sector = pathfindingDatum.Sectors[s]; var vertices = new HashSet <short>(); if (sector.FirstLink == -1) { continue; } var link = pathfindingDatum.Links[sector.FirstLink]; while (true) { if (link.LeftSector == s) { vertices.Add(link.Vertex1); vertices.Add(link.Vertex2); if (link.ForwardLink == sector.FirstLink) { break; } else { link = pathfindingDatum.Links[link.ForwardLink]; } } else if (link.RightSector == s) { vertices.Add(link.Vertex1); vertices.Add(link.Vertex2); if (link.ReverseLink == sector.FirstLink) { break; } else { link = pathfindingDatum.Links[link.ReverseLink]; } } } var points = new List <RealPoint3d>(); var xlist = new List <float>(); var ylist = new List <float>(); var zlist = new List <float>(); foreach (var vert in vertices) { points.Add(pathfindingDatum.Vertices[vert].Position); xlist.Add(pathfindingDatum.Vertices[vert].Position.X); ylist.Add(pathfindingDatum.Vertices[vert].Position.Y); zlist.Add(pathfindingDatum.Vertices[vert].Position.Z); } float xmin = xlist.Min(); float xmax = xlist.Max(); float ymin = ylist.Min(); float ymax = ylist.Max(); float zmin = zlist.Min(); float zmax = zlist.Max(); float zave = zlist.Average(); bool pnpoly(List <RealPoint3d> polygon, RealPoint3d testPoint) { var result = false; for (int p = 0, j = polygon.Count - 1; p < polygon.Count(); j = p++) { if (polygon[p].Y < testPoint.Y && polygon[j].Y >= testPoint.Y || polygon[j].Y < testPoint.Y && polygon[p].Y >= testPoint.Y) { if (polygon[p].X + (testPoint.Y - polygon[p].Y) / (polygon[j].Y - polygon[p].Y) * (polygon[j].X - polygon[p].X) < testPoint.X) { result = !result; } } } // TODO: maybe check Z? return(result); } if (pnpoly(points, new RealPoint3d(hint_x, hint_y, hint_z))) { sectorlist.Add(s); zavelist.Add(Math.Abs(hint_z - zave)); } else if (xmin < hint_x && xmax > hint_x && ymin < hint_y && ymax > hint_y) { backupsectorlist.Add(s); backupzavelist.Add(Math.Abs(hint_z - zave)); } } if (sectorlist.Count > 0) { var s = sectorlist[zavelist.IndexOf(zavelist.Min())]; var hiword = (short)(hint.Data[3] >> 16); hint.Data[3] = hiword << 16 | s; success = true; } else if (backupsectorlist.Count > 0) { var s = backupsectorlist[backupzavelist.IndexOf(backupzavelist.Min())]; var hiword = (short)(hint.Data[3] >> 16); hint.Data[3] = hiword << 16 | s; success = true; } if (!success) { Console.WriteLine($"Pathfinding Jump Hint {i} sector not found!"); } } resourceStream.Position = pathfindingDatum.PathfindingHints.Address.Offset; for (var i = 0; i < pathfindingDatum.PathfindingHints.Count; i++) { CacheContext.Serializer.Serialize(dataContext, pathfindingDatum.PathfindingHints[i]); } resourceStream.Position = 0; CacheContext.ReplaceResource(Definition.PathfindingResource, resourceStream); } } return(true); }
public override object Execute(List <string> args) { // Deserialize the definition data var resourceContext = new ResourceSerializationContext(CacheContext, BSP.CollisionBspResource); var definition = CacheContext.Deserializer.Deserialize <StructureBspTagResources>(resourceContext); // Extract the resource data var resourceDataStream = new MemoryStream(); CacheContext.ExtractResource(BSP.CollisionBspResource, resourceDataStream); using (var reader = new EndianReader(resourceDataStream)) { #region collision bsps foreach (var cbsp in definition.CollisionBsps) { reader.BaseStream.Position = cbsp.Bsp3dNodes.Address.Offset; for (var i = 0; i < cbsp.Bsp3dNodes.Count; i++) { var element = CacheContext.Deserializer.DeserializeValue(reader, null, null, typeof(CollisionGeometry.Bsp3dNode)); cbsp.Bsp3dNodes.Add((CollisionGeometry.Bsp3dNode)element); } reader.BaseStream.Position = cbsp.Planes.Address.Offset; for (var i = 0; i < cbsp.Planes.Count; i++) { var element = CacheContext.Deserializer.DeserializeValue(reader, null, null, typeof(CollisionGeometry.Plane)); cbsp.Planes.Add((CollisionGeometry.Plane)element); } reader.BaseStream.Position = cbsp.Leaves.Address.Offset; for (var i = 0; i < cbsp.Leaves.Count; i++) { var element = CacheContext.Deserializer.DeserializeValue(reader, null, null, typeof(CollisionGeometry.Leaf)); cbsp.Leaves.Add((CollisionGeometry.Leaf)element); } reader.BaseStream.Position = cbsp.Bsp2dReferences.Address.Offset; for (var i = 0; i < cbsp.Bsp2dReferences.Count; i++) { var element = CacheContext.Deserializer.DeserializeValue(reader, null, null, typeof(CollisionGeometry.Bsp2dReference)); cbsp.Bsp2dReferences.Add((CollisionGeometry.Bsp2dReference)element); } reader.BaseStream.Position = cbsp.Bsp2dNodes.Address.Offset; for (var i = 0; i < cbsp.Bsp2dNodes.Count; i++) { var element = CacheContext.Deserializer.DeserializeValue(reader, null, null, typeof(CollisionGeometry.Bsp2dNode)); cbsp.Bsp2dNodes.Add((CollisionGeometry.Bsp2dNode)element); } reader.BaseStream.Position = cbsp.Surfaces.Address.Offset; for (var i = 0; i < cbsp.Surfaces.Count; i++) { var element = CacheContext.Deserializer.DeserializeValue(reader, null, null, typeof(CollisionGeometry.Surface)); cbsp.Surfaces.Add((CollisionGeometry.Surface)element); } reader.BaseStream.Position = cbsp.Edges.Address.Offset; for (var i = 0; i < cbsp.Edges.Count; i++) { var element = CacheContext.Deserializer.DeserializeValue(reader, null, null, typeof(CollisionGeometry.Edge)); cbsp.Edges.Add((CollisionGeometry.Edge)element); } reader.BaseStream.Position = cbsp.Vertices.Address.Offset; for (var i = 0; i < cbsp.Vertices.Count; i++) { var element = CacheContext.Deserializer.DeserializeValue(reader, null, null, typeof(CollisionGeometry.Vertex)); cbsp.Vertices.Add((CollisionGeometry.Vertex)element); } } #endregion #region large collision bsps foreach (var cbsp in definition.LargeCollisionBsps) { reader.BaseStream.Position = cbsp.Bsp3dNodes.Address.Offset; for (var i = 0; i < cbsp.Bsp3dNodes.Count; i++) { var element = CacheContext.Deserializer.DeserializeValue(reader, null, null, typeof(StructureBspTagResources.LargeCollisionBspBlock.Bsp3dNode)); cbsp.Bsp3dNodes.Add((StructureBspTagResources.LargeCollisionBspBlock.Bsp3dNode)element); } reader.BaseStream.Position = cbsp.Planes.Address.Offset; for (var i = 0; i < cbsp.Planes.Count; i++) { var element = CacheContext.Deserializer.DeserializeValue(reader, null, null, typeof(CollisionGeometry.Plane)); cbsp.Planes.Add((CollisionGeometry.Plane)element); } reader.BaseStream.Position = cbsp.Leaves.Address.Offset; for (var i = 0; i < cbsp.Leaves.Count; i++) { var element = CacheContext.Deserializer.DeserializeValue(reader, null, null, typeof(CollisionGeometry.Leaf)); cbsp.Leaves.Add((CollisionGeometry.Leaf)element); } reader.BaseStream.Position = cbsp.Bsp2dReferences.Address.Offset; for (var i = 0; i < cbsp.Bsp2dReferences.Count; i++) { var element = CacheContext.Deserializer.DeserializeValue(reader, null, null, typeof(StructureBspTagResources.LargeCollisionBspBlock.Bsp2dReference)); cbsp.Bsp2dReferences.Add((StructureBspTagResources.LargeCollisionBspBlock.Bsp2dReference)element); } reader.BaseStream.Position = cbsp.Bsp2dNodes.Address.Offset; for (var i = 0; i < cbsp.Bsp2dNodes.Count; i++) { var element = CacheContext.Deserializer.DeserializeValue(reader, null, null, typeof(StructureBspTagResources.LargeCollisionBspBlock.Bsp2dNode)); cbsp.Bsp2dNodes.Add((StructureBspTagResources.LargeCollisionBspBlock.Bsp2dNode)element); } reader.BaseStream.Position = cbsp.Surfaces.Address.Offset; for (var i = 0; i < cbsp.Surfaces.Count; i++) { var element = CacheContext.Deserializer.DeserializeValue(reader, null, null, typeof(StructureBspTagResources.LargeCollisionBspBlock.Surface)); cbsp.Surfaces.Add((StructureBspTagResources.LargeCollisionBspBlock.Surface)element); } reader.BaseStream.Position = cbsp.Edges.Address.Offset; for (var i = 0; i < cbsp.Edges.Count; i++) { var element = CacheContext.Deserializer.DeserializeValue(reader, null, null, typeof(StructureBspTagResources.LargeCollisionBspBlock.Edge)); cbsp.Edges.Add((StructureBspTagResources.LargeCollisionBspBlock.Edge)element); } reader.BaseStream.Position = cbsp.Vertices.Address.Offset; for (var i = 0; i < cbsp.Vertices.Count; i++) { var element = CacheContext.Deserializer.DeserializeValue(reader, null, null, typeof(StructureBspTagResources.LargeCollisionBspBlock.Vertex)); cbsp.Vertices.Add((StructureBspTagResources.LargeCollisionBspBlock.Vertex)element); } } #endregion #region compressions foreach (var instance in definition.InstancedGeometry) { #region compression's resource data reader.BaseStream.Position = instance.CollisionInfo.Bsp3dNodes.Address.Offset; for (var i = 0; i < instance.CollisionInfo.Bsp3dNodes.Count; i++) { var element = CacheContext.Deserializer.DeserializeValue(reader, null, null, typeof(CollisionGeometry.Bsp3dNode)); instance.CollisionInfo.Bsp3dNodes.Add((CollisionGeometry.Bsp3dNode)element); } reader.BaseStream.Position = instance.CollisionInfo.Planes.Address.Offset; for (var i = 0; i < instance.CollisionInfo.Planes.Count; i++) { var element = CacheContext.Deserializer.DeserializeValue(reader, null, null, typeof(CollisionGeometry.Plane)); instance.CollisionInfo.Planes.Add((CollisionGeometry.Plane)element); } reader.BaseStream.Position = instance.CollisionInfo.Leaves.Address.Offset; for (var i = 0; i < instance.CollisionInfo.Leaves.Count; i++) { var element = CacheContext.Deserializer.DeserializeValue(reader, null, null, typeof(CollisionGeometry.Leaf)); instance.CollisionInfo.Leaves.Add((CollisionGeometry.Leaf)element); } reader.BaseStream.Position = instance.CollisionInfo.Bsp2dReferences.Address.Offset; for (var i = 0; i < instance.CollisionInfo.Bsp2dReferences.Count; i++) { var element = CacheContext.Deserializer.DeserializeValue(reader, null, null, typeof(CollisionGeometry.Bsp2dReference)); instance.CollisionInfo.Bsp2dReferences.Add((CollisionGeometry.Bsp2dReference)element); } reader.BaseStream.Position = instance.CollisionInfo.Bsp2dNodes.Address.Offset; for (var i = 0; i < instance.CollisionInfo.Bsp2dNodes.Count; i++) { var element = CacheContext.Deserializer.DeserializeValue(reader, null, null, typeof(CollisionGeometry.Bsp2dNode)); instance.CollisionInfo.Bsp2dNodes.Add((CollisionGeometry.Bsp2dNode)element); } reader.BaseStream.Position = instance.CollisionInfo.Surfaces.Address.Offset; for (var i = 0; i < instance.CollisionInfo.Surfaces.Count; i++) { var element = CacheContext.Deserializer.DeserializeValue(reader, null, null, typeof(CollisionGeometry.Surface)); instance.CollisionInfo.Surfaces.Add((CollisionGeometry.Surface)element); } reader.BaseStream.Position = instance.CollisionInfo.Edges.Address.Offset; for (var i = 0; i < instance.CollisionInfo.Edges.Count; i++) { var element = CacheContext.Deserializer.DeserializeValue(reader, null, null, typeof(CollisionGeometry.Edge)); instance.CollisionInfo.Edges.Add((CollisionGeometry.Edge)element); } reader.BaseStream.Position = instance.CollisionInfo.Vertices.Address.Offset; for (var i = 0; i < instance.CollisionInfo.Vertices.Count; i++) { var element = CacheContext.Deserializer.DeserializeValue(reader, null, null, typeof(CollisionGeometry.Vertex)); instance.CollisionInfo.Vertices.Add((CollisionGeometry.Vertex)element); } #endregion #region compression's other resource data foreach (var cbsp in instance.CollisionGeometries) { reader.BaseStream.Position = cbsp.Bsp3dNodes.Address.Offset; for (var i = 0; i < cbsp.Bsp3dNodes.Count; i++) { var element = CacheContext.Deserializer.DeserializeValue(reader, null, null, typeof(CollisionGeometry.Bsp3dNode)); cbsp.Bsp3dNodes.Add((CollisionGeometry.Bsp3dNode)element); } reader.BaseStream.Position = cbsp.Planes.Address.Offset; for (var i = 0; i < cbsp.Planes.Count; i++) { var element = CacheContext.Deserializer.DeserializeValue(reader, null, null, typeof(CollisionGeometry.Plane)); cbsp.Planes.Add((CollisionGeometry.Plane)element); } reader.BaseStream.Position = cbsp.Leaves.Address.Offset; for (var i = 0; i < cbsp.Leaves.Count; i++) { var element = CacheContext.Deserializer.DeserializeValue(reader, null, null, typeof(CollisionGeometry.Leaf)); cbsp.Leaves.Add((CollisionGeometry.Leaf)element); } reader.BaseStream.Position = cbsp.Bsp2dReferences.Address.Offset; for (var i = 0; i < cbsp.Bsp2dReferences.Count; i++) { var element = CacheContext.Deserializer.DeserializeValue(reader, null, null, typeof(CollisionGeometry.Bsp2dReference)); cbsp.Bsp2dReferences.Add((CollisionGeometry.Bsp2dReference)element); } reader.BaseStream.Position = cbsp.Bsp2dNodes.Address.Offset; for (var i = 0; i < cbsp.Bsp2dNodes.Count; i++) { var element = CacheContext.Deserializer.DeserializeValue(reader, null, null, typeof(CollisionGeometry.Bsp2dNode)); cbsp.Bsp2dNodes.Add((CollisionGeometry.Bsp2dNode)element); } reader.BaseStream.Position = cbsp.Surfaces.Address.Offset; for (var i = 0; i < cbsp.Surfaces.Count; i++) { var element = CacheContext.Deserializer.DeserializeValue(reader, null, null, typeof(CollisionGeometry.Surface)); cbsp.Surfaces.Add((CollisionGeometry.Surface)element); } reader.BaseStream.Position = cbsp.Edges.Address.Offset; for (var i = 0; i < cbsp.Edges.Count; i++) { var element = CacheContext.Deserializer.DeserializeValue(reader, null, null, typeof(CollisionGeometry.Edge)); cbsp.Edges.Add((CollisionGeometry.Edge)element); } reader.BaseStream.Position = cbsp.Vertices.Address.Offset; for (var i = 0; i < cbsp.Vertices.Count; i++) { var element = CacheContext.Deserializer.DeserializeValue(reader, null, null, typeof(CollisionGeometry.Vertex)); cbsp.Vertices.Add((CollisionGeometry.Vertex)element); } } #endregion #region Unknown Data for (var i = 0; i < instance.Unknown1.Count; i++) { var element = CacheContext.Deserializer.DeserializeValue(reader, null, null, typeof(StructureBspTagResources.InstancedGeometryBlock.Unknown1Block)); instance.Unknown1.Add((StructureBspTagResources.InstancedGeometryBlock.Unknown1Block)element); } for (var i = 0; i < instance.Unknown2.Count; i++) { var element = CacheContext.Deserializer.DeserializeValue(reader, null, null, typeof(StructureBspTagResources.InstancedGeometryBlock.Unknown2Block)); instance.Unknown2.Add((StructureBspTagResources.InstancedGeometryBlock.Unknown2Block)element); } for (var i = 0; i < instance.Unknown3.Count; i++) { var element = CacheContext.Deserializer.DeserializeValue(reader, null, null, typeof(StructureBspTagResources.InstancedGeometryBlock.Unknown3Block)); instance.Unknown3.Add((StructureBspTagResources.InstancedGeometryBlock.Unknown3Block)element); } #endregion #region compression's havok collision data foreach (var collision in instance.BspPhysics) { for (var i = 0; i < collision.Data.Count; i++) { var element = CacheContext.Deserializer.DeserializeValue(reader, null, null, typeof(byte)); collision.Data.Add(new StructureBspTagResources.CollisionBspPhysicsBlock.Datum { Value = (byte)element }); } } #endregion } #endregion } return(true); }
public override object Execute(List <string> args) { if (args.Count != 3) { return(false); } var variantName = args[0]; var fileType = args[1].ToLower(); var modelFileName = args[2]; switch (fileType) { case "obj": case "amf": case "dae": break; default: throw new NotImplementedException(fileType); } // // 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 modelVariant = Definition.Variants.FirstOrDefault(v => (CacheContext.GetString(v.Name) ?? v.Name.ToString()) == variantName); if (modelVariant == null && Definition.Variants.Count > 0 && fileType != "dae") { Console.WriteLine("Unable to find variant \"{0}\"", variantName); Console.WriteLine("Use \"listvariants\" to list available variants."); return(true); } // // Deserialize the render model tag // RenderModel renderModel; using (var cacheStream = CacheContext.TagCacheFile.OpenRead()) { renderModel = CacheContext.Deserialize <RenderModel>(cacheStream, Definition.RenderModel); } 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(CacheContext, renderModel.Geometry.Resource); var resourceDefinition = CacheContext.Deserialize <RenderGeometryApiResourceDefinition>(resourceContext); using (var resourceStream = new MemoryStream()) { // // Extract the resource data // CacheContext.ExtractResource(renderModel.Geometry.Resource, resourceStream); var modelFile = new FileInfo(modelFileName); if (!modelFile.Directory.Exists) { modelFile.Directory.Create(); } switch (fileType) { case "obj": ExtractObj(modelFile, renderModel, modelVariant, resourceDefinition, resourceStream); break; case "amf": ExtractAmf(modelFile, renderModel, modelVariant, resourceDefinition, resourceStream); break; case "dae": ModelExtractor extractor = new ModelExtractor(CacheContext, renderModel); extractor.ExtractRenderModel(); extractor.ExportCollada(modelFile); break; default: throw new NotImplementedException(fileType); } } Console.WriteLine("Done!"); return(true); }
public override object Execute(List <string> args) { string variantName; string fileType; string modelFileName; if (args.Count == 2) { variantName = "*"; fileType = args[0].ToLower(); modelFileName = args[1]; } else if (args.Count == 3) { variantName = args[0]; fileType = args[1].ToLower(); modelFileName = args[2]; } else { return(false); } switch (fileType) { case "obj": case "dae": break; default: throw new NotImplementedException(fileType); } if (Definition.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(CacheContext, Definition.Geometry.Resource); var resourceDefinition = CacheContext.Deserializer.Deserialize <RenderGeometryApiResourceDefinition>(resourceContext); using (var resourceStream = new MemoryStream()) { // // Extract the resource data // CacheContext.ExtractResource(Definition.Geometry.Resource, resourceStream); var modelFile = new FileInfo(modelFileName); if (!modelFile.Directory.Exists) { modelFile.Directory.Create(); } ModelExtractor extractor = new ModelExtractor(CacheContext, Definition); extractor.ExtractRenderModel(variantName); switch (fileType) { case "obj": return(extractor.ExportObject(modelFile)); case "dae": return(extractor.ExportCollada(modelFile)); default: throw new NotImplementedException(fileType); } } }
public override object Execute(List <string> args) { if (args.Count != 1) { return(false); } var outDirectory = args[0]; if (!Directory.Exists(outDirectory)) { Console.Write("Destination directory does not exist. Create it? [y/n] "); var answer = Console.ReadLine().ToLower(); if (answer.Length == 0 || !(answer.StartsWith("y") || answer.StartsWith("n"))) { return(false); } if (answer.StartsWith("y")) { Directory.CreateDirectory(outDirectory); } else { return(false); } } var resource = Definition.Resource; var resourceContext = new ResourceSerializationContext(CacheContext, resource); var resourceDefinition = CacheContext.Deserializer.Deserialize <SoundResourceDefinition>(resourceContext); if (resourceDefinition.Data == null) { Console.WriteLine("Invalid sound definition"); return(false); } var dataReference = resourceDefinition.Data; byte[] soundData = new byte[dataReference.Size]; var resourceDataStream = new MemoryStream(soundData); CacheContext.ExtractResource(resource, resourceDataStream); for (int i = 0; i < Definition.PitchRanges.Count; i++) { var pitchRange = Definition.PitchRanges[i]; for (int j = 0; j < pitchRange.Permutations.Count; j++) { var permutation = pitchRange.Permutations[j]; var filename = Tag.Index.ToString("X8") + "_" + i.ToString() + "_" + j.ToString(); byte[] permutationData = new byte[permutation.PermutationChunks[0].EncodedSize & 0x3FFFFFF]; Array.Copy(soundData, permutation.PermutationChunks[0].Offset, permutationData, 0, permutationData.Length); switch (Definition.PlatformCodec.Compression) { case Compression.PCM: filename += ".wav"; break; case Compression.MP3: filename += ".mp3"; break; case Compression.FSB4: filename += ".fsb"; break; } var outPath = Path.Combine(outDirectory, filename); using (EndianWriter writer = new EndianWriter(new FileStream(outPath, FileMode.Create, FileAccess.Write, FileShare.None), EndianFormat.BigEndian)) { var channelCount = Encoding.GetChannelCount(Definition.PlatformCodec.Encoding); var sampleRate = Definition.SampleRate.GetSampleRateHz(); switch (Definition.PlatformCodec.Compression) { case Compression.PCM: WAVFile WAVfile = new WAVFile(permutationData, channelCount, sampleRate); WAVfile.Write(writer); break; case Compression.MP3: case Compression.FSB4: writer.Write(permutationData); break; } } } } Console.WriteLine("Done!"); 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); }
public override object Execute(List <string> args) { if (args.Count != 0) { return(false); } if (Definition.CollisionBspResource == null) { Console.WriteLine("ERROR: Collision geometry does not have a resource associated with it."); return(true); } var resourceDefinition = CacheContext.Deserialize <StructureBspTagResources>(Definition.CollisionBspResource); using (var resourceStream = new MemoryStream()) { CacheContext.ExtractResource(Definition.CollisionBspResource, resourceStream); using (var reader = new EndianReader(resourceStream)) { foreach (var cbsp in resourceDefinition.CollisionBsps) { reader.BaseStream.Position = cbsp.Bsp3dNodes.Address.Offset; for (var i = 0; i < cbsp.Bsp3dNodes.Count; i++) { var element = CacheContext.Deserializer.DeserializeValue(reader, null, null, typeof(CollisionGeometry.Bsp3dNode)); cbsp.Bsp3dNodes.Add((CollisionGeometry.Bsp3dNode)element); } reader.BaseStream.Position = cbsp.Planes.Address.Offset; for (var i = 0; i < cbsp.Planes.Count; i++) { var element = CacheContext.Deserializer.DeserializeValue(reader, null, null, typeof(CollisionGeometry.Plane)); cbsp.Planes.Add((CollisionGeometry.Plane)element); } reader.BaseStream.Position = cbsp.Leaves.Address.Offset; for (var i = 0; i < cbsp.Leaves.Count; i++) { var element = CacheContext.Deserializer.DeserializeValue(reader, null, null, typeof(CollisionGeometry.Leaf)); cbsp.Leaves.Add((CollisionGeometry.Leaf)element); } reader.BaseStream.Position = cbsp.Bsp2dReferences.Address.Offset; for (var i = 0; i < cbsp.Bsp2dReferences.Count; i++) { var element = CacheContext.Deserializer.DeserializeValue(reader, null, null, typeof(CollisionGeometry.Bsp2dReference)); cbsp.Bsp2dReferences.Add((CollisionGeometry.Bsp2dReference)element); } reader.BaseStream.Position = cbsp.Bsp2dNodes.Address.Offset; for (var i = 0; i < cbsp.Bsp2dNodes.Count; i++) { var element = CacheContext.Deserializer.DeserializeValue(reader, null, null, typeof(CollisionGeometry.Bsp2dNode)); cbsp.Bsp2dNodes.Add((CollisionGeometry.Bsp2dNode)element); } reader.BaseStream.Position = cbsp.Surfaces.Address.Offset; for (var i = 0; i < cbsp.Surfaces.Count; i++) { var element = CacheContext.Deserializer.DeserializeValue(reader, null, null, typeof(CollisionGeometry.Surface)); cbsp.Surfaces.Add((CollisionGeometry.Surface)element); } reader.BaseStream.Position = cbsp.Edges.Address.Offset; for (var i = 0; i < cbsp.Edges.Count; i++) { var element = CacheContext.Deserializer.DeserializeValue(reader, null, null, typeof(CollisionGeometry.Edge)); cbsp.Edges.Add((CollisionGeometry.Edge)element); } reader.BaseStream.Position = cbsp.Vertices.Address.Offset; for (var i = 0; i < cbsp.Vertices.Count; i++) { var element = CacheContext.Deserializer.DeserializeValue(reader, null, null, typeof(CollisionGeometry.Vertex)); cbsp.Vertices.Add((CollisionGeometry.Vertex)element); } } foreach (var cbsp in resourceDefinition.LargeCollisionBsps) { reader.BaseStream.Position = cbsp.Bsp3dNodes.Address.Offset; for (var i = 0; i < cbsp.Bsp3dNodes.Count; i++) { var element = CacheContext.Deserializer.DeserializeValue(reader, null, null, typeof(StructureBspTagResources.LargeCollisionBspBlock.Bsp3dNode)); cbsp.Bsp3dNodes.Add((StructureBspTagResources.LargeCollisionBspBlock.Bsp3dNode)element); } reader.BaseStream.Position = cbsp.Planes.Address.Offset; for (var i = 0; i < cbsp.Planes.Count; i++) { var element = CacheContext.Deserializer.DeserializeValue(reader, null, null, typeof(CollisionGeometry.Plane)); cbsp.Planes.Add((CollisionGeometry.Plane)element); } reader.BaseStream.Position = cbsp.Leaves.Address.Offset; for (var i = 0; i < cbsp.Leaves.Count; i++) { var element = CacheContext.Deserializer.DeserializeValue(reader, null, null, typeof(CollisionGeometry.Leaf)); cbsp.Leaves.Add((CollisionGeometry.Leaf)element); } reader.BaseStream.Position = cbsp.Bsp2dReferences.Address.Offset; for (var i = 0; i < cbsp.Bsp2dReferences.Count; i++) { var element = CacheContext.Deserializer.DeserializeValue(reader, null, null, typeof(StructureBspTagResources.LargeCollisionBspBlock.Bsp2dReference)); cbsp.Bsp2dReferences.Add((StructureBspTagResources.LargeCollisionBspBlock.Bsp2dReference)element); } reader.BaseStream.Position = cbsp.Bsp2dNodes.Address.Offset; for (var i = 0; i < cbsp.Bsp2dNodes.Count; i++) { var element = CacheContext.Deserializer.DeserializeValue(reader, null, null, typeof(StructureBspTagResources.LargeCollisionBspBlock.Bsp2dNode)); cbsp.Bsp2dNodes.Add((StructureBspTagResources.LargeCollisionBspBlock.Bsp2dNode)element); } reader.BaseStream.Position = cbsp.Surfaces.Address.Offset; for (var i = 0; i < cbsp.Surfaces.Count; i++) { var element = CacheContext.Deserializer.DeserializeValue(reader, null, null, typeof(StructureBspTagResources.LargeCollisionBspBlock.Surface)); cbsp.Surfaces.Add((StructureBspTagResources.LargeCollisionBspBlock.Surface)element); } reader.BaseStream.Position = cbsp.Edges.Address.Offset; for (var i = 0; i < cbsp.Edges.Count; i++) { var element = CacheContext.Deserializer.DeserializeValue(reader, null, null, typeof(StructureBspTagResources.LargeCollisionBspBlock.Edge)); cbsp.Edges.Add((StructureBspTagResources.LargeCollisionBspBlock.Edge)element); } reader.BaseStream.Position = cbsp.Vertices.Address.Offset; for (var i = 0; i < cbsp.Vertices.Count; i++) { var element = CacheContext.Deserializer.DeserializeValue(reader, null, null, typeof(StructureBspTagResources.LargeCollisionBspBlock.Vertex)); cbsp.Vertices.Add((StructureBspTagResources.LargeCollisionBspBlock.Vertex)element); } } foreach (var instance in resourceDefinition.InstancedGeometry) { reader.BaseStream.Position = instance.CollisionInfo.Bsp3dNodes.Address.Offset; for (var i = 0; i < instance.CollisionInfo.Bsp3dNodes.Count; i++) { var element = CacheContext.Deserializer.DeserializeValue(reader, null, null, typeof(CollisionGeometry.Bsp3dNode)); instance.CollisionInfo.Bsp3dNodes.Add((CollisionGeometry.Bsp3dNode)element); } reader.BaseStream.Position = instance.CollisionInfo.Planes.Address.Offset; for (var i = 0; i < instance.CollisionInfo.Planes.Count; i++) { var element = CacheContext.Deserializer.DeserializeValue(reader, null, null, typeof(CollisionGeometry.Plane)); instance.CollisionInfo.Planes.Add((CollisionGeometry.Plane)element); } reader.BaseStream.Position = instance.CollisionInfo.Leaves.Address.Offset; for (var i = 0; i < instance.CollisionInfo.Leaves.Count; i++) { var element = CacheContext.Deserializer.DeserializeValue(reader, null, null, typeof(CollisionGeometry.Leaf)); instance.CollisionInfo.Leaves.Add((CollisionGeometry.Leaf)element); } reader.BaseStream.Position = instance.CollisionInfo.Bsp2dReferences.Address.Offset; for (var i = 0; i < instance.CollisionInfo.Bsp2dReferences.Count; i++) { var element = CacheContext.Deserializer.DeserializeValue(reader, null, null, typeof(CollisionGeometry.Bsp2dReference)); instance.CollisionInfo.Bsp2dReferences.Add((CollisionGeometry.Bsp2dReference)element); } reader.BaseStream.Position = instance.CollisionInfo.Bsp2dNodes.Address.Offset; for (var i = 0; i < instance.CollisionInfo.Bsp2dNodes.Count; i++) { var element = CacheContext.Deserializer.DeserializeValue(reader, null, null, typeof(CollisionGeometry.Bsp2dNode)); instance.CollisionInfo.Bsp2dNodes.Add((CollisionGeometry.Bsp2dNode)element); } reader.BaseStream.Position = instance.CollisionInfo.Surfaces.Address.Offset; for (var i = 0; i < instance.CollisionInfo.Surfaces.Count; i++) { var element = CacheContext.Deserializer.DeserializeValue(reader, null, null, typeof(CollisionGeometry.Surface)); instance.CollisionInfo.Surfaces.Add((CollisionGeometry.Surface)element); } reader.BaseStream.Position = instance.CollisionInfo.Edges.Address.Offset; for (var i = 0; i < instance.CollisionInfo.Edges.Count; i++) { var element = CacheContext.Deserializer.DeserializeValue(reader, null, null, typeof(CollisionGeometry.Edge)); instance.CollisionInfo.Edges.Add((CollisionGeometry.Edge)element); } reader.BaseStream.Position = instance.CollisionInfo.Vertices.Address.Offset; for (var i = 0; i < instance.CollisionInfo.Vertices.Count; i++) { var element = CacheContext.Deserializer.DeserializeValue(reader, null, null, typeof(CollisionGeometry.Vertex)); instance.CollisionInfo.Vertices.Add((CollisionGeometry.Vertex)element); } foreach (var cbsp in instance.CollisionGeometries) { reader.BaseStream.Position = cbsp.Bsp3dNodes.Address.Offset; for (var i = 0; i < cbsp.Bsp3dNodes.Count; i++) { var element = CacheContext.Deserializer.DeserializeValue(reader, null, null, typeof(CollisionGeometry.Bsp3dNode)); cbsp.Bsp3dNodes.Add((CollisionGeometry.Bsp3dNode)element); } reader.BaseStream.Position = cbsp.Planes.Address.Offset; for (var i = 0; i < cbsp.Planes.Count; i++) { var element = CacheContext.Deserializer.DeserializeValue(reader, null, null, typeof(CollisionGeometry.Plane)); cbsp.Planes.Add((CollisionGeometry.Plane)element); } reader.BaseStream.Position = cbsp.Leaves.Address.Offset; for (var i = 0; i < cbsp.Leaves.Count; i++) { var element = CacheContext.Deserializer.DeserializeValue(reader, null, null, typeof(CollisionGeometry.Leaf)); cbsp.Leaves.Add((CollisionGeometry.Leaf)element); } reader.BaseStream.Position = cbsp.Bsp2dReferences.Address.Offset; for (var i = 0; i < cbsp.Bsp2dReferences.Count; i++) { var element = CacheContext.Deserializer.DeserializeValue(reader, null, null, typeof(CollisionGeometry.Bsp2dReference)); cbsp.Bsp2dReferences.Add((CollisionGeometry.Bsp2dReference)element); } reader.BaseStream.Position = cbsp.Bsp2dNodes.Address.Offset; for (var i = 0; i < cbsp.Bsp2dNodes.Count; i++) { var element = CacheContext.Deserializer.DeserializeValue(reader, null, null, typeof(CollisionGeometry.Bsp2dNode)); cbsp.Bsp2dNodes.Add((CollisionGeometry.Bsp2dNode)element); } reader.BaseStream.Position = cbsp.Surfaces.Address.Offset; for (var i = 0; i < cbsp.Surfaces.Count; i++) { var element = CacheContext.Deserializer.DeserializeValue(reader, null, null, typeof(CollisionGeometry.Surface)); cbsp.Surfaces.Add((CollisionGeometry.Surface)element); } reader.BaseStream.Position = cbsp.Edges.Address.Offset; for (var i = 0; i < cbsp.Edges.Count; i++) { var element = CacheContext.Deserializer.DeserializeValue(reader, null, null, typeof(CollisionGeometry.Edge)); cbsp.Edges.Add((CollisionGeometry.Edge)element); } reader.BaseStream.Position = cbsp.Vertices.Address.Offset; for (var i = 0; i < cbsp.Vertices.Count; i++) { var element = CacheContext.Deserializer.DeserializeValue(reader, null, null, typeof(CollisionGeometry.Vertex)); cbsp.Vertices.Add((CollisionGeometry.Vertex)element); } } for (var i = 0; i < instance.Unknown1.Count; i++) { var element = CacheContext.Deserializer.DeserializeValue(reader, null, null, typeof(StructureBspTagResources.InstancedGeometryBlock.Unknown1Block)); instance.Unknown1.Add((StructureBspTagResources.InstancedGeometryBlock.Unknown1Block)element); } for (var i = 0; i < instance.Unknown2.Count; i++) { var element = CacheContext.Deserializer.DeserializeValue(reader, null, null, typeof(StructureBspTagResources.InstancedGeometryBlock.Unknown2Block)); instance.Unknown2.Add((StructureBspTagResources.InstancedGeometryBlock.Unknown2Block)element); } for (var i = 0; i < instance.Unknown3.Count; i++) { var element = CacheContext.Deserializer.DeserializeValue(reader, null, null, typeof(StructureBspTagResources.InstancedGeometryBlock.Unknown3Block)); instance.Unknown3.Add((StructureBspTagResources.InstancedGeometryBlock.Unknown3Block)element); } foreach (var collision in instance.BspPhysics) { for (var i = 0; i < collision.Data.Count; i++) { var element = CacheContext.Deserializer.DeserializeValue(reader, null, null, typeof(byte)); collision.Data.Add(new StructureBspTagResources.CollisionBspPhysicsBlock.Datum { Value = (byte)element }); } } } } } Definition.TagResources = new List <ScenarioStructureBsp.TagResourcesBlock> { new ScenarioStructureBsp.TagResourcesBlock { CollisionBsps = resourceDefinition.CollisionBsps.Select( x => new CollisionGeometry { Bsp3dNodes = x.Bsp3dNodes.Elements, Planes = x.Planes.Elements, Leaves = x.Leaves.Elements, Bsp2dReferences = x.Bsp2dReferences.Elements, Bsp2dNodes = x.Bsp2dNodes.Elements, Surfaces = x.Surfaces.Elements, Edges = x.Edges.Elements, Vertices = x.Vertices.Elements }).ToList(), LargeCollisionBsps = resourceDefinition.LargeCollisionBsps.Select( x => new ScenarioStructureBsp.TagResourcesBlock.LargeCollisionBspBlock { Bsp3dNodes = x.Bsp3dNodes.Elements, Planes = x.Planes.Elements, Leaves = x.Leaves.Elements, Bsp2dReferences = x.Bsp2dReferences.Elements, Bsp2dNodes = x.Bsp2dNodes.Elements, Surfaces = x.Surfaces.Elements, Edges = x.Edges.Elements, Vertices = x.Vertices.Elements }).ToList(), InstancedGeometry = resourceDefinition.InstancedGeometry.Select( x => new ScenarioStructureBsp.TagResourcesBlock.InstancedGeometryBlock { Checksum = x.Checksum, BoundingSphereOffset = x.BoundingSphereOffset, BoundingSphereRadius = x.BoundingSphereRadius, CollisionInfo = new CollisionGeometry { Bsp3dNodes = x.CollisionInfo.Bsp3dNodes.Elements, Planes = x.CollisionInfo.Planes.Elements, Leaves = x.CollisionInfo.Leaves.Elements, Bsp2dReferences = x.CollisionInfo.Bsp2dReferences.Elements, Bsp2dNodes = x.CollisionInfo.Bsp2dNodes.Elements, Surfaces = x.CollisionInfo.Surfaces.Elements, Edges = x.CollisionInfo.Edges.Elements, Vertices = x.CollisionInfo.Vertices.Elements }, CollisionGeometries = x.CollisionGeometries.Select( y => new CollisionGeometry { Bsp3dNodes = y.Bsp3dNodes.Elements, Planes = y.Planes.Elements, Leaves = y.Leaves.Elements, Bsp2dReferences = y.Bsp2dReferences.Elements, Bsp2dNodes = y.Bsp2dNodes.Elements, Surfaces = y.Surfaces.Elements, Edges = y.Edges.Elements, Vertices = y.Vertices.Elements }).ToList(), BspPhysics = x.BspPhysics.Select( y => new ScenarioStructureBsp.TagResourcesBlock.CollisionBspPhysicsBlock { Unused1 = y.Unused1, Size = y.Size, Count = y.Count, Address = y.Address, Unused2 = y.Unused2, Offset = y.Offset, Unused3 = y.Unused3, DataSize = y.DataSize, DataCapacityAndFlags = y.DataCapacityAndFlags, DataBuildType = y.DataBuildType, Unused4 = y.Unused4, Unused5 = y.Unused5, Data = y.Data.Elements, MoppBuildType = y.MoppBuildType, Unused6 = y.Unused6, Unused7 = y.Unused7 }).ToList(), Unknown1 = x.Unknown1.Elements, Unknown2 = x.Unknown2.Elements, Unknown3 = x.Unknown3.Elements, MeshIndex = x.MeshIndex, CompressionIndex = x.CompressionIndex, Unknown4 = x.Unknown4, Unknown5 = x.Unknown5.Elements, Unknown6 = x.Unknown6 }).ToList(), HavokData = resourceDefinition.HavokData } }; return(true); }
public override object Execute(List <string> args) { if (args.Count != 1) { return(false); } if (Definition.PathfindingResource == null) { Console.WriteLine("ERROR: Pathfinding geometry does not have a resource associated with it."); return(true); } var resourceContext = new ResourceSerializationContext(CacheContext, Definition.PathfindingResource); var resourceDefinition = CacheContext.Deserializer.Deserialize <StructureBspCacheFileTagResources>(resourceContext); using (var resourceStream = new MemoryStream()) using (var reader = new EndianReader(resourceStream)) { CacheContext.ExtractResource(Definition.PathfindingResource, resourceStream); var dataContext = new DataSerializationContext(reader); foreach (var pathfindingDatum in resourceDefinition.PathfindingData) { resourceStream.Position = pathfindingDatum.Sectors.Address.Offset; for (var i = 0; i < pathfindingDatum.Sectors.Count; i++) { pathfindingDatum.Sectors.Add( CacheContext.Deserializer.Deserialize <ScenarioStructureBsp.PathfindingDatum.Sector>(dataContext)); } resourceStream.Position = pathfindingDatum.Links.Address.Offset; for (var i = 0; i < pathfindingDatum.Links.Count; i++) { pathfindingDatum.Links.Add( CacheContext.Deserializer.Deserialize <ScenarioStructureBsp.PathfindingDatum.Link>(dataContext)); } resourceStream.Position = pathfindingDatum.References.Address.Offset; for (var i = 0; i < pathfindingDatum.References.Count; i++) { pathfindingDatum.References.Add( CacheContext.Deserializer.Deserialize <ScenarioStructureBsp.PathfindingDatum.Reference>(dataContext)); } resourceStream.Position = pathfindingDatum.Bsp2dNodes.Address.Offset; for (var i = 0; i < pathfindingDatum.Bsp2dNodes.Count; i++) { pathfindingDatum.Bsp2dNodes.Add( CacheContext.Deserializer.Deserialize <ScenarioStructureBsp.PathfindingDatum.Bsp2dNode>(dataContext)); } resourceStream.Position = pathfindingDatum.PathfindingHints.Address.Offset; for (var i = 0; i < pathfindingDatum.PathfindingHints.Count; i++) { pathfindingDatum.PathfindingHints.Add( CacheContext.Deserializer.Deserialize <ScenarioStructureBsp.PathfindingDatum.PathfindingHint>(dataContext)); } resourceStream.Position = pathfindingDatum.Vertices.Address.Offset; for (var i = 0; i < pathfindingDatum.Vertices.Count; i++) { pathfindingDatum.Vertices.Add( CacheContext.Deserializer.Deserialize <ScenarioStructureBsp.PathfindingDatum.Vertex>(dataContext)); } for (var objRefIdx = 0; objRefIdx < pathfindingDatum.ObjectReferences.Count; objRefIdx++) { for (var bspRefIdx = 0; bspRefIdx < pathfindingDatum.ObjectReferences[objRefIdx].Bsps.Count; bspRefIdx++) { var bspRef = pathfindingDatum.ObjectReferences[objRefIdx].Bsps[bspRefIdx]; resourceStream.Position = bspRef.Bsp2dRefs.Address.Offset; for (var bsp2dRefIdx = 0; bsp2dRefIdx < bspRef.Bsp2dRefs.Count; bsp2dRefIdx++) { bspRef.Bsp2dRefs.Add( CacheContext.Deserializer.Deserialize <ScenarioStructureBsp.PathfindingDatum.ObjectReference.BspReference.Bsp2dRef>(dataContext)); } } } resourceStream.Position = pathfindingDatum.InstancedGeometryReferences.Address.Offset; for (var i = 0; i < pathfindingDatum.InstancedGeometryReferences.Count; i++) { pathfindingDatum.InstancedGeometryReferences.Add( CacheContext.Deserializer.Deserialize <ScenarioStructureBsp.PathfindingDatum.InstancedGeometryReference>(dataContext)); } resourceStream.Position = pathfindingDatum.Doors.Address.Offset; for (var i = 0; i < pathfindingDatum.Doors.Count; i++) { pathfindingDatum.Doors.Add( CacheContext.Deserializer.Deserialize <ScenarioStructureBsp.PathfindingDatum.Door>(dataContext)); } } } using (var writer = File.CreateText(args[0])) { foreach (var pathfinding in resourceDefinition.PathfindingData) { writer.WriteLine("mtllib Blue.mtl"); foreach (ScenarioStructureBsp.PathfindingDatum.Vertex vertex in pathfinding.Vertices) { writer.WriteLine($"v {vertex.Position.X} {vertex.Position.Z} {vertex.Position.Y}"); } writer.WriteLine("usemtl Blue"); writer.WriteLine("g JumpHints"); for (var i = 0; i < pathfinding.PathfindingHints.Count; i++) { var hint = pathfinding.PathfindingHints[i]; if (hint.HintType == ScenarioStructureBsp.PathfindingDatum.PathfindingHint.HintTypeValue.JumpLink) { int v2 = (hint.Data[0] >> 16) + 1; int v1 = (hint.Data[0] & 0xFFFF) + 1; int v4 = (hint.Data[1] >> 16) + 1; int v3 = (hint.Data[1] & 0xFFFF) + 1; int landing = hint.Data[3] & 0xFFFF; writer.WriteLine($"o JumpHint {i}, Landing Sector {landing}"); writer.WriteLine($"f {v1} {v2} {v4} {v3}"); } } writer.WriteLine("usemtl White"); writer.WriteLine("g Sectors"); for (var i = 0; i < pathfinding.Sectors.Count; i++) { var sector = pathfinding.Sectors[i]; var vertices = new HashSet <short>(); var link = pathfinding.Links[sector.FirstLink]; writer.WriteLine($"o Sector {i}"); writer.Write("f"); while (true) { if (link.LeftSector == i) { writer.Write($" {link.Vertex1 + 1}"); if (link.ForwardLink == sector.FirstLink) { break; } else { link = pathfinding.Links[link.ForwardLink]; } } else if (link.RightSector == i) { writer.Write($" {link.Vertex2 + 1}"); if (link.ReverseLink == sector.FirstLink) { break; } else { link = pathfinding.Links[link.ReverseLink]; } } } writer.WriteLine(); } } } return(true); }