private TagResourceReference ConvertStructureBspTagResources(ScenarioStructureBsp bsp) { StructureBspTagResources resourceDefinition = BlamCache.ResourceCache.GetStructureBspTagResources(bsp.CollisionBspResource); // probably can remove all the code here if (resourceDefinition == null) { return(null); } if (BlamCache.Version < CacheVersion.Halo3ODST) { // convert surface planes foreach (var instance in resourceDefinition.InstancedGeometry) { foreach (var surfacePlane in instance.SurfacePlanes) { surfacePlane.PlaneCountNew = surfacePlane.PlaneCountOld; surfacePlane.PlaneIndexNew = surfacePlane.PlaneIndexOld; } foreach (var mopps in instance.CollisionMoppCodes) { mopps.Data.Elements = HavokConverter.ConvertMoppCodes(BlamCache.Version, CacheContext.Version, mopps.Data.Elements); } } } bsp.CollisionBspResource = CacheContext.ResourceCache.CreateStructureBspResource(resourceDefinition); return(bsp.CollisionBspResource); }
public GeometryToObjectConverter( GameCacheHaloOnlineBase destCache, Stream destStream, GameCache sourceCache, Stream sourceStream, Scenario scenario, int structureBspIndex) { DestCache = destCache; DestStream = destStream; SourceCache = sourceCache; SourceStream = sourceStream; StructureBspIndex = structureBspIndex; PortTag = new PortTagCommand(destCache, sourceCache); PortTag.SetFlags(PortTagCommand.PortingFlags.Default); Scenario = scenario; StructureBspIndex = structureBspIndex; StructureBsp = SourceCache.Deserialize <ScenarioStructureBsp>(SourceStream, Scenario.StructureBsps[structureBspIndex].StructureBsp); sLdT = SourceCache.Deserialize <ScenarioLightmap>(SourceStream, Scenario.Lightmap); if (SourceCache.Version >= CacheVersion.Halo3ODST) { Lbsp = SourceCache.Deserialize <ScenarioLightmapBspData>(SourceStream, sLdT.LightmapDataReferences[StructureBspIndex]); } else { Lbsp = sLdT.Lightmaps[StructureBspIndex]; } var resourceDefinition = SourceCache.ResourceCache.GetRenderGeometryApiResourceDefinition(Lbsp.Geometry.Resource); Lbsp.Geometry.SetResourceBuffers(resourceDefinition); StructureBspResources = SourceCache.ResourceCache.GetStructureBspTagResources(StructureBsp.CollisionBspResource); }
public MoppDataCommand(ScenarioStructureBsp bsp) : base(true, "MoppData", "Modify Mopp data", "MoppData <export/import/parse> <output/input file>", "") { Definition = bsp; }
public DumpMoppCommand(HaloOnlineCacheContext cacheContext, ScenarioStructureBsp bsp) : base(true, "DumpMopp", "Dumps bsp mopp.", "DumpMopp <Output File>", "") { CacheContext = cacheContext; Definition = bsp; }
public MoppDataCommand(HaloOnlineCacheContext cacheContext, ScenarioStructureBsp bsp) : base(true, "MoppData", "Modify Mopp data", "MoppData <export/import/parse> <output/input file>", "") { CacheContext = cacheContext; Definition = bsp; }
public ExtractPathfindingGeometryCommand(HaloOnlineCacheContext cacheContext, ScenarioStructureBsp definition) : base(true, "ExtractPathfindingGeometry", "", "ExtractPathfindingGeometry <OBJ File>", "") { CacheContext = cacheContext; Definition = definition; }
public ExtractCollisionGeometryCommand(HaloOnlineCacheContext cacheContext, ScenarioStructureBsp definition) : base(false, "ExtractCollisionGeometry", "", "ExtractCollisionGeometry <OBJ File>", "") { CacheContext = cacheContext; Definition = definition; }
public ExtractPathfindingGeometryCommand(GameCache cache, ScenarioStructureBsp definition) : base(true, "ExtractPathfindingGeometry", "", "ExtractPathfindingGeometry <OBJ File>", "") { Cache = cache; Definition = definition; }
public GenerateJumpHintsCommand(HaloOnlineCacheContext cacheContext, ScenarioStructureBsp definition) : base(true, "GenerateJumpHints", "Generates jump hint data for pre-ODST bsp pathfinding data.", "GenerateJumpHints", "Generates jump hint data for pre-ODST bsp pathfinding data.") { CacheContext = cacheContext; Definition = definition; }
public GenerateJumpHintsCommand(GameCache cache, CachedTag tag, ScenarioStructureBsp definition) : base(true, "GenerateJumpHints", "Generates jump hint data for pre-ODST bsp pathfinding data.", "GenerateJumpHints", "Generates jump hint data for pre-ODST bsp pathfinding data.") { Cache = cache; Definition = definition; Tag = tag; }
public ExtractRenderGeometryCommand(HaloOnlineCacheContext cacheContext, ScenarioStructureBsp definition) : base(true, "ExtractRenderGeometry", "Extracts render geometry from the current scenario_structure_bsp definition.", "ExtractRenderGeometry <filetype> <filename>", "Extracts render geometry from the current scenario_structure_bsp definition.\n" + "Supported file types: obj") { CacheContext = cacheContext; Definition = definition; }
public LocalizeTagResourcesCommand(HaloOnlineCacheContext cacheContext, ScenarioStructureBsp definition, CachedTagInstance tag) : base(true, "LocalizeTagResources", "", "LocalizeTagResources", "") { CacheContext = cacheContext; Definition = definition; Tag = tag; }
public CollisionTestCommand(HaloOnlineCacheContext cacheContext, CachedTagInstance tag, ScenarioStructureBsp bsp) : base(true, "CollisionTest", "A test resource-loading command for 'sbsp' tag collision.", "collision-test", "A test resource-loading command for 'sbsp' tag collision.") { CacheContext = cacheContext; Tag = tag; BSP = bsp; }
public ResourceDataCommand(HaloOnlineCacheContext cacheContext, CachedTagInstance tag, ScenarioStructureBsp definition) : base(false, "ResourceData", "SbspResource Extract/Import <Resource Type> <Filename>", "ResourceData Extract/Import a sbsp resource.", "Extract/Import a sbsp resource. Resource types: \n" + "Geometry \n" + "Geometry2 \n" + "CollisionBspResource \n" + "PathfindingResource \n") { CacheContext = cacheContext; Tag = tag; Definition = definition; }
public static CommandContext Create(CommandContext parent, HaloOnlineCacheContext cacheContext, CachedTagInstance tag, ScenarioStructureBsp bsp) { var groupName = cacheContext.GetString(tag.Group.Name); var context = new CommandContext(parent, string.Format("{0:X8}.{1}", tag.Index, groupName)); Populate(context, cacheContext, tag, bsp); return(context); }
private PageableResource ConvertStructureBspTagResources(ScenarioStructureBsp bsp, Dictionary <ResourceLocation, Stream> resourceStreams) { // // Set up ElDorado resource reference // bsp.CollisionBspResource = new PageableResource { Page = new RawPage { Index = -1 }, Resource = new TagResourceGen3 { ResourceType = TagResourceTypeGen3.Collision, DefinitionData = new byte[0x30], DefinitionAddress = new CacheResourceAddress(CacheResourceAddressType.Definition, 0), ResourceFixups = new List <TagResourceGen3.ResourceFixup>(), ResourceDefinitionFixups = new List <TagResourceGen3.ResourceDefinitionFixup>(), Unknown2 = 1 } }; // // Port Blam resource definition // var resourceEntry = BlamCache.ResourceGestalt.TagResources[bsp.ZoneAssetIndex3.Index]; bsp.CollisionBspResource.Resource.DefinitionAddress = resourceEntry.DefinitionAddress; bsp.CollisionBspResource.Resource.DefinitionData = BlamCache.ResourceGestalt.FixupInformation.Skip(resourceEntry.FixupInformationOffset).Take(resourceEntry.FixupInformationLength).ToArray(); StructureBspTagResources resourceDefinition = null; using (var definitionStream = new MemoryStream(bsp.CollisionBspResource.Resource.DefinitionData, true)) using (var definitionReader = new EndianReader(definitionStream, EndianFormat.BigEndian)) using (var definitionWriter = new EndianWriter(definitionStream, EndianFormat.BigEndian)) { foreach (var fixup in resourceEntry.ResourceFixups) { var newFixup = new TagResourceGen3.ResourceFixup { BlockOffset = (uint)fixup.BlockOffset, Address = new CacheResourceAddress( fixup.Type == 4 ? CacheResourceAddressType.Resource : CacheResourceAddressType.Definition, fixup.Offset) }; definitionStream.Position = newFixup.BlockOffset; definitionWriter.Write(newFixup.Address.Value); bsp.CollisionBspResource.Resource.ResourceFixups.Add(newFixup); } var dataContext = new DataSerializationContext(definitionReader, definitionWriter, CacheResourceAddressType.Definition); definitionStream.Position = bsp.CollisionBspResource.Resource.DefinitionAddress.Offset; resourceDefinition = BlamCache.Deserializer.Deserialize <StructureBspTagResources>(dataContext); // // Apply game-specific fixes to the resource definition // if (BlamCache.Version < CacheVersion.Halo3ODST) { resourceDefinition.LargeCollisionBsps = new List <StructureBspTagResources.LargeCollisionBspBlock>(); resourceDefinition.HavokData = new List <StructureBspTagResources.HavokDatum>(); } foreach (var instance in resourceDefinition.InstancedGeometry) { instance.Unknown5 = new TagBlock <StructureBspTagResources.InstancedGeometryBlock.Unknown4Block>(); instance.Unknown2 = new TagBlock <StructureBspTagResources.InstancedGeometryBlock.Unknown2Block>(); } } // // Load Blam resource data // var resourceData = BlamCache.GetRawFromID(bsp.ZoneAssetIndex3); if (resourceData == null) { CacheContext.Serializer.Serialize(new ResourceSerializationContext(CacheContext, bsp.CollisionBspResource), resourceDefinition); return(bsp.CollisionBspResource); } // // Port Blam resource to ElDorado resource cache // using (var blamResourceStream = resourceData != null ? new MemoryStream(resourceData) : new MemoryStream()) using (var resourceReader = new EndianReader(blamResourceStream, EndianFormat.BigEndian)) using (var dataStream = new MemoryStream()) using (var resourceWriter = new EndianWriter(dataStream, EndianFormat.LittleEndian)) { var dataContext = new DataSerializationContext(resourceReader, resourceWriter); foreach (var collisionBsp in resourceDefinition.CollisionBsps) { StreamUtil.Align(dataStream, 0x10); blamResourceStream.Position = collisionBsp.Bsp3dNodes.Address.Offset; collisionBsp.Bsp3dNodes.Address = new CacheResourceAddress(CacheResourceAddressType.Resource, (int)dataStream.Position); for (var i = 0; i < collisionBsp.Bsp3dNodes.Count; i++) { CacheContext.Serializer.Serialize(dataContext, BlamCache.Deserializer.Deserialize <CollisionGeometry.Bsp3dNode>(dataContext)); } StreamUtil.Align(dataStream, 0x10); blamResourceStream.Position = collisionBsp.Planes.Address.Offset; collisionBsp.Planes.Address = new CacheResourceAddress(CacheResourceAddressType.Resource, (int)dataStream.Position); for (var i = 0; i < collisionBsp.Planes.Count; i++) { CacheContext.Serializer.Serialize(dataContext, BlamCache.Deserializer.Deserialize <CollisionGeometry.Plane>(dataContext)); } StreamUtil.Align(dataStream, 0x10); blamResourceStream.Position = collisionBsp.Leaves.Address.Offset; collisionBsp.Leaves.Address = new CacheResourceAddress(CacheResourceAddressType.Resource, (int)dataStream.Position); for (var i = 0; i < collisionBsp.Leaves.Count; i++) { CacheContext.Serializer.Serialize(dataContext, BlamCache.Deserializer.Deserialize <CollisionGeometry.Leaf>(dataContext)); } StreamUtil.Align(dataStream, 0x10); // 0x4 > 0x10 blamResourceStream.Position = collisionBsp.Bsp2dReferences.Address.Offset; collisionBsp.Bsp2dReferences.Address = new CacheResourceAddress(CacheResourceAddressType.Resource, (int)dataStream.Position); for (var i = 0; i < collisionBsp.Bsp2dReferences.Count; i++) { CacheContext.Serializer.Serialize(dataContext, BlamCache.Deserializer.Deserialize <CollisionGeometry.Bsp2dReference>(dataContext)); } StreamUtil.Align(dataStream, 0x10); blamResourceStream.Position = collisionBsp.Bsp2dNodes.Address.Offset; collisionBsp.Bsp2dNodes.Address = new CacheResourceAddress(CacheResourceAddressType.Resource, (int)dataStream.Position); for (var i = 0; i < collisionBsp.Bsp2dNodes.Count; i++) { CacheContext.Serializer.Serialize(dataContext, BlamCache.Deserializer.Deserialize <CollisionGeometry.Bsp2dNode>(dataContext)); } StreamUtil.Align(dataStream, 0x10); blamResourceStream.Position = collisionBsp.Surfaces.Address.Offset; collisionBsp.Surfaces.Address = new CacheResourceAddress(CacheResourceAddressType.Resource, (int)dataStream.Position); for (var i = 0; i < collisionBsp.Surfaces.Count; i++) { var surface = BlamCache.Deserializer.Deserialize <CollisionGeometry.Surface>(dataContext); CacheContext.Serializer.Serialize(dataContext, surface); } StreamUtil.Align(dataStream, 0x10); // 0x4 > 0x10 blamResourceStream.Position = collisionBsp.Edges.Address.Offset; collisionBsp.Edges.Address = new CacheResourceAddress(CacheResourceAddressType.Resource, (int)dataStream.Position); for (var i = 0; i < collisionBsp.Edges.Count; i++) { CacheContext.Serializer.Serialize(dataContext, BlamCache.Deserializer.Deserialize <CollisionGeometry.Edge>(dataContext)); } StreamUtil.Align(dataStream, 0x10); blamResourceStream.Position = collisionBsp.Vertices.Address.Offset; collisionBsp.Vertices.Address = new CacheResourceAddress(CacheResourceAddressType.Resource, (int)dataStream.Position); for (var i = 0; i < collisionBsp.Vertices.Count; i++) { CacheContext.Serializer.Serialize(dataContext, BlamCache.Deserializer.Deserialize <CollisionGeometry.Vertex>(dataContext)); } } foreach (var largeCollisionBsp in resourceDefinition.LargeCollisionBsps) { StreamUtil.Align(dataStream, 0x10); blamResourceStream.Position = largeCollisionBsp.Bsp3dNodes.Address.Offset; largeCollisionBsp.Bsp3dNodes.Address = new CacheResourceAddress(CacheResourceAddressType.Resource, (int)dataStream.Position); for (var i = 0; i < largeCollisionBsp.Bsp3dNodes.Count; i++) { CacheContext.Serializer.Serialize(dataContext, BlamCache.Deserializer.Deserialize <StructureBspTagResources.LargeCollisionBspBlock.Bsp3dNode>(dataContext)); } StreamUtil.Align(dataStream, 0x10); blamResourceStream.Position = largeCollisionBsp.Planes.Address.Offset; largeCollisionBsp.Planes.Address = new CacheResourceAddress(CacheResourceAddressType.Resource, (int)dataStream.Position); for (var i = 0; i < largeCollisionBsp.Planes.Count; i++) { CacheContext.Serializer.Serialize(dataContext, BlamCache.Deserializer.Deserialize <CollisionGeometry.Plane>(dataContext)); } StreamUtil.Align(dataStream, 0x10); blamResourceStream.Position = largeCollisionBsp.Leaves.Address.Offset; largeCollisionBsp.Leaves.Address = new CacheResourceAddress(CacheResourceAddressType.Resource, (int)dataStream.Position); for (var i = 0; i < largeCollisionBsp.Leaves.Count; i++) { CacheContext.Serializer.Serialize(dataContext, BlamCache.Deserializer.Deserialize <CollisionGeometry.Leaf>(dataContext)); } StreamUtil.Align(dataStream, 0x10); blamResourceStream.Position = largeCollisionBsp.Bsp2dReferences.Address.Offset; largeCollisionBsp.Bsp2dReferences.Address = new CacheResourceAddress(CacheResourceAddressType.Resource, (int)dataStream.Position); for (var i = 0; i < largeCollisionBsp.Bsp2dReferences.Count; i++) { CacheContext.Serializer.Serialize(dataContext, BlamCache.Deserializer.Deserialize <StructureBspTagResources.LargeCollisionBspBlock.Bsp2dReference>(dataContext)); } StreamUtil.Align(dataStream, 0x10); blamResourceStream.Position = largeCollisionBsp.Bsp2dNodes.Address.Offset; largeCollisionBsp.Bsp2dNodes.Address = new CacheResourceAddress(CacheResourceAddressType.Resource, (int)dataStream.Position); for (var i = 0; i < largeCollisionBsp.Bsp2dNodes.Count; i++) { CacheContext.Serializer.Serialize(dataContext, BlamCache.Deserializer.Deserialize <StructureBspTagResources.LargeCollisionBspBlock.Bsp2dNode>(dataContext)); } StreamUtil.Align(dataStream, 0x10); blamResourceStream.Position = largeCollisionBsp.Surfaces.Address.Offset; largeCollisionBsp.Surfaces.Address = new CacheResourceAddress(CacheResourceAddressType.Resource, (int)dataStream.Position); for (var i = 0; i < largeCollisionBsp.Surfaces.Count; i++) { var surface = BlamCache.Deserializer.Deserialize <StructureBspTagResources.LargeCollisionBspBlock.Surface>(dataContext); // surface.Material = PortGlobalMaterialIndex(CacheContext, BlamCache, surface.Material); CacheContext.Serializer.Serialize(dataContext, surface); } StreamUtil.Align(dataStream, 0x10); // 0x4 > 0x10 blamResourceStream.Position = largeCollisionBsp.Edges.Address.Offset; largeCollisionBsp.Edges.Address = new CacheResourceAddress(CacheResourceAddressType.Resource, (int)dataStream.Position); for (var i = 0; i < largeCollisionBsp.Edges.Count; i++) { CacheContext.Serializer.Serialize(dataContext, BlamCache.Deserializer.Deserialize <StructureBspTagResources.LargeCollisionBspBlock.Edge>(dataContext)); } StreamUtil.Align(dataStream, 0x10); blamResourceStream.Position = largeCollisionBsp.Vertices.Address.Offset; largeCollisionBsp.Vertices.Address = new CacheResourceAddress(CacheResourceAddressType.Resource, (int)dataStream.Position); for (var i = 0; i < largeCollisionBsp.Vertices.Count; i++) { CacheContext.Serializer.Serialize(dataContext, BlamCache.Deserializer.Deserialize <StructureBspTagResources.LargeCollisionBspBlock.Vertex>(dataContext)); } } foreach (var instance in resourceDefinition.InstancedGeometry) { StreamUtil.Align(dataStream, 0x10); // 0x8 > 0x10 blamResourceStream.Position = instance.CollisionInfo.Bsp3dNodes.Address.Offset; instance.CollisionInfo.Bsp3dNodes.Address = new CacheResourceAddress(CacheResourceAddressType.Resource, (int)dataStream.Position); for (var i = 0; i < instance.CollisionInfo.Bsp3dNodes.Count; i++) { CacheContext.Serializer.Serialize(dataContext, BlamCache.Deserializer.Deserialize <CollisionGeometry.Bsp3dNode>(dataContext)); } StreamUtil.Align(dataStream, 0x10); blamResourceStream.Position = instance.CollisionInfo.Planes.Address.Offset; instance.CollisionInfo.Planes.Address = new CacheResourceAddress(CacheResourceAddressType.Resource, (int)dataStream.Position); for (var i = 0; i < instance.CollisionInfo.Planes.Count; i++) { CacheContext.Serializer.Serialize(dataContext, BlamCache.Deserializer.Deserialize <CollisionGeometry.Plane>(dataContext)); } StreamUtil.Align(dataStream, 0x10); blamResourceStream.Position = instance.CollisionInfo.Leaves.Address.Offset; instance.CollisionInfo.Leaves.Address = new CacheResourceAddress(CacheResourceAddressType.Resource, (int)dataStream.Position); for (var i = 0; i < instance.CollisionInfo.Leaves.Count; i++) { CacheContext.Serializer.Serialize(dataContext, BlamCache.Deserializer.Deserialize <CollisionGeometry.Leaf>(dataContext)); } StreamUtil.Align(dataStream, 0x10); // 0x4 > 0x10 blamResourceStream.Position = instance.CollisionInfo.Bsp2dReferences.Address.Offset; instance.CollisionInfo.Bsp2dReferences.Address = new CacheResourceAddress(CacheResourceAddressType.Resource, (int)dataStream.Position); for (var i = 0; i < instance.CollisionInfo.Bsp2dReferences.Count; i++) { CacheContext.Serializer.Serialize(dataContext, BlamCache.Deserializer.Deserialize <CollisionGeometry.Bsp2dReference>(dataContext)); } StreamUtil.Align(dataStream, 0x10); blamResourceStream.Position = instance.CollisionInfo.Bsp2dNodes.Address.Offset; instance.CollisionInfo.Bsp2dNodes.Address = new CacheResourceAddress(CacheResourceAddressType.Resource, (int)dataStream.Position); for (var i = 0; i < instance.CollisionInfo.Bsp2dNodes.Count; i++) { CacheContext.Serializer.Serialize(dataContext, BlamCache.Deserializer.Deserialize <CollisionGeometry.Bsp2dNode>(dataContext)); } StreamUtil.Align(dataStream, 0x10); blamResourceStream.Position = instance.CollisionInfo.Surfaces.Address.Offset; instance.CollisionInfo.Surfaces.Address = new CacheResourceAddress(CacheResourceAddressType.Resource, (int)dataStream.Position); for (var i = 0; i < instance.CollisionInfo.Surfaces.Count; i++) { var surface = BlamCache.Deserializer.Deserialize <CollisionGeometry.Surface>(dataContext); // surface.Material = PortGlobalMaterialIndex(CacheContext, BlamCache, surface.Material); CacheContext.Serializer.Serialize(dataContext, surface); } StreamUtil.Align(dataStream, 0x10); // 0x4 > 0x10 blamResourceStream.Position = instance.CollisionInfo.Edges.Address.Offset; instance.CollisionInfo.Edges.Address = new CacheResourceAddress(CacheResourceAddressType.Resource, (int)dataStream.Position); for (var i = 0; i < instance.CollisionInfo.Edges.Count; i++) { CacheContext.Serializer.Serialize(dataContext, BlamCache.Deserializer.Deserialize <CollisionGeometry.Edge>(dataContext)); } StreamUtil.Align(dataStream, 0x10); blamResourceStream.Position = instance.CollisionInfo.Vertices.Address.Offset; instance.CollisionInfo.Vertices.Address = new CacheResourceAddress(CacheResourceAddressType.Resource, (int)dataStream.Position); for (var i = 0; i < instance.CollisionInfo.Vertices.Count; i++) { CacheContext.Serializer.Serialize(dataContext, BlamCache.Deserializer.Deserialize <CollisionGeometry.Vertex>(dataContext)); } foreach (var collisionGeometry in instance.CollisionGeometries) { StreamUtil.Align(dataStream, 0x10); // 0x8 > 0x10 blamResourceStream.Position = collisionGeometry.Bsp3dNodes.Address.Offset; collisionGeometry.Bsp3dNodes.Address = new CacheResourceAddress(CacheResourceAddressType.Resource, (int)dataStream.Position); for (var i = 0; i < collisionGeometry.Bsp3dNodes.Count; i++) { CacheContext.Serializer.Serialize(dataContext, BlamCache.Deserializer.Deserialize <CollisionGeometry.Bsp3dNode>(dataContext)); } StreamUtil.Align(dataStream, 0x10); blamResourceStream.Position = collisionGeometry.Planes.Address.Offset; collisionGeometry.Planes.Address = new CacheResourceAddress(CacheResourceAddressType.Resource, (int)dataStream.Position); for (var i = 0; i < collisionGeometry.Planes.Count; i++) { CacheContext.Serializer.Serialize(dataContext, BlamCache.Deserializer.Deserialize <CollisionGeometry.Plane>(dataContext)); } StreamUtil.Align(dataStream, 0x10); blamResourceStream.Position = collisionGeometry.Leaves.Address.Offset; collisionGeometry.Leaves.Address = new CacheResourceAddress(CacheResourceAddressType.Resource, (int)dataStream.Position); for (var i = 0; i < collisionGeometry.Leaves.Count; i++) { CacheContext.Serializer.Serialize(dataContext, BlamCache.Deserializer.Deserialize <CollisionGeometry.Leaf>(dataContext)); } StreamUtil.Align(dataStream, 0x10); blamResourceStream.Position = collisionGeometry.Bsp2dReferences.Address.Offset; collisionGeometry.Bsp2dReferences.Address = new CacheResourceAddress(CacheResourceAddressType.Resource, (int)dataStream.Position); for (var i = 0; i < collisionGeometry.Bsp2dReferences.Count; i++) { CacheContext.Serializer.Serialize(dataContext, BlamCache.Deserializer.Deserialize <CollisionGeometry.Bsp2dReference>(dataContext)); } StreamUtil.Align(dataStream, 0x10); blamResourceStream.Position = collisionGeometry.Bsp2dNodes.Address.Offset; collisionGeometry.Bsp2dNodes.Address = new CacheResourceAddress(CacheResourceAddressType.Resource, (int)dataStream.Position); for (var i = 0; i < collisionGeometry.Bsp2dNodes.Count; i++) { CacheContext.Serializer.Serialize(dataContext, BlamCache.Deserializer.Deserialize <CollisionGeometry.Bsp2dNode>(dataContext)); } StreamUtil.Align(dataStream, 0x10); blamResourceStream.Position = collisionGeometry.Surfaces.Address.Offset; collisionGeometry.Surfaces.Address = new CacheResourceAddress(CacheResourceAddressType.Resource, (int)dataStream.Position); for (var i = 0; i < collisionGeometry.Surfaces.Count; i++) { var surface = BlamCache.Deserializer.Deserialize <CollisionGeometry.Surface>(dataContext); // surface.Material = PortGlobalMaterialIndex(CacheContext, BlamCache, surface.Material); CacheContext.Serializer.Serialize(dataContext, surface); } StreamUtil.Align(dataStream, 0x10); // 0x4 > 0x10 blamResourceStream.Position = collisionGeometry.Edges.Address.Offset; collisionGeometry.Edges.Address = new CacheResourceAddress(CacheResourceAddressType.Resource, (int)dataStream.Position); for (var i = 0; i < collisionGeometry.Edges.Count; i++) { CacheContext.Serializer.Serialize(dataContext, BlamCache.Deserializer.Deserialize <CollisionGeometry.Edge>(dataContext)); } StreamUtil.Align(dataStream, 0x10); blamResourceStream.Position = collisionGeometry.Vertices.Address.Offset; collisionGeometry.Vertices.Address = new CacheResourceAddress(CacheResourceAddressType.Resource, (int)dataStream.Position); for (var i = 0; i < collisionGeometry.Vertices.Count; i++) { CacheContext.Serializer.Serialize(dataContext, BlamCache.Deserializer.Deserialize <CollisionGeometry.Vertex>(dataContext)); } } foreach (var moppCode in instance.BspPhysics) { StreamUtil.Align(dataStream, 0x10); blamResourceStream.Position = moppCode.Data.Address.Offset; moppCode.Data.Address = new CacheResourceAddress(CacheResourceAddressType.Resource, (int)dataStream.Position); var moppData = resourceReader.ReadBytes(moppCode.Data.Count).Select(i => new CollisionMoppCode.Datum { Value = i }).ToList(); if (BlamCache.Version < CacheVersion.Halo3ODST) { moppData = ConvertCollisionMoppData(moppData); } resourceWriter.Write(moppData.Select(i => i.Value).ToArray()); } StreamUtil.Align(dataStream, 0x10); // 0x4 > 0x10 blamResourceStream.Position = instance.Unknown1.Address.Offset; instance.Unknown1.Address = new CacheResourceAddress(CacheResourceAddressType.Resource, (int)dataStream.Position); for (var i = 0; i < instance.Unknown1.Count; i++) { CacheContext.Serializer.Serialize(dataContext, BlamCache.Deserializer.Deserialize <StructureBspTagResources.InstancedGeometryBlock.Unknown1Block>(dataContext)); } /* * StreamUtil.Align(dataStream, 0x4); // 0x4 > 0x10 * blamResourceStream.Position = instance.Unknown2.Address.Offset; * instance.Unknown2.Address = new CacheAddress(CacheAddressType.Resource, (int)dataStream.Position); * for (var i = 0; i < instance.Unknown2.Count; i++) * { * var element = BlamCache.Deserializer.Deserialize<StructureBspTagResources.InstancedGeometryBlock.Unknown2Block>(dataContext); * if (BlamCache.Version <= CacheVersion.Halo3ODST) * { * element.Unknown1 = element.Unknown1_H3; * element.Unknown2 = element.Unknown2_H3; * } * CacheContext.Serializer.Serialize(dataContext, element); */ StreamUtil.Align(dataStream, 0x10); // 0x4 > 0x10 blamResourceStream.Position = instance.Unknown3.Address.Offset; instance.Unknown3.Address = new CacheResourceAddress(CacheResourceAddressType.Resource, (int)dataStream.Position); for (var i = 0; i < instance.Unknown3.Count; i++) { CacheContext.Serializer.Serialize(dataContext, BlamCache.Deserializer.Deserialize <StructureBspTagResources.InstancedGeometryBlock.Unknown3Block>(dataContext)); } } dataStream.Position = 0; CacheContext.Serializer.Serialize(new ResourceSerializationContext(CacheContext, bsp.CollisionBspResource), resourceDefinition); bsp.CollisionBspResource.ChangeLocation(ResourceLocation.ResourcesB); var resource = bsp.CollisionBspResource; if (resource == null) { throw new ArgumentNullException("resource"); } if (!dataStream.CanRead) { throw new ArgumentException("The input stream is not open for reading", "dataStream"); } var cache = CacheContext.GetResourceCache(ResourceLocation.ResourcesB); if (!resourceStreams.ContainsKey(ResourceLocation.ResourcesB)) { resourceStreams[ResourceLocation.ResourcesB] = FlagIsSet(PortingFlags.Memory) ? new MemoryStream() : (Stream)CacheContext.OpenResourceCacheReadWrite(ResourceLocation.ResourcesB); if (FlagIsSet(PortingFlags.Memory)) { using (var resourceStream = CacheContext.OpenResourceCacheRead(ResourceLocation.ResourcesB)) resourceStream.CopyTo(resourceStreams[ResourceLocation.ResourcesB]); } } var dataSize = (int)(dataStream.Length - dataStream.Position); var data = new byte[dataSize]; dataStream.Read(data, 0, dataSize); resource.Page.Index = cache.Add(resourceStreams[ResourceLocation.ResourcesB], data, out uint compressedSize); resource.Page.CompressedBlockSize = compressedSize; resource.Page.UncompressedBlockSize = (uint)dataSize; resource.DisableChecksum(); } return(bsp.CollisionBspResource); }
private static bool ImportResource(ScenarioStructureBsp Definition, HaloOnlineCacheContext CacheContext, IReadOnlyList <string> args) { if (args.Count != 4) { return(false); } var location = args[1].Split(".".ToCharArray()).Length == 2 ? args[1].Split(".".ToCharArray())[0] : args[1]; // resources.dat or resources var resourceType = args[2].ToLower(); // geometry2 var filePath = args[3]; // sc140_000_geometry2.raw var resourceLocation = ResourceLocation.Resources; switch (location) { case "audio": resourceLocation = ResourceLocation.Audio; break; case "resources": resourceLocation = ResourceLocation.Resources; break; case "resources_b": case "video": resourceLocation = ResourceLocation.ResourcesB; break; case "textures": resourceLocation = ResourceLocation.Textures; break; case "textures_b": resourceLocation = ResourceLocation.TexturesB; break; case "lightmaps": resourceLocation = ResourceLocation.Lightmaps; break; case "render_models": resourceLocation = ResourceLocation.RenderModels; break; default: Console.WriteLine($"ERROR: Cache location is incorrect."); return(false); } using (var stream = File.Open(filePath, FileMode.Open, FileAccess.ReadWrite)) { switch (resourceType) { case "geometry": Definition.Geometry.Resource.ChangeLocation(resourceLocation); CacheContext.AddResource(Definition.Geometry.Resource, stream); Console.WriteLine($"New Geometry resource index = {Definition.Geometry.Resource.Page.Index:X4}; {Definition.Geometry.Resource.Page.Index:D4}"); break; case "geometry2": Definition.Geometry2.Resource.ChangeLocation(resourceLocation); CacheContext.AddResource(Definition.Geometry2.Resource, stream); Console.WriteLine($"New Geometry2 resource index = {Definition.Geometry2.Resource.Page.Index:X4}; {Definition.Geometry2.Resource.Page.Index:D4}"); break; case "collisionbspresource": Definition.CollisionBspResource.ChangeLocation(resourceLocation); CacheContext.AddResource(Definition.CollisionBspResource, stream); Console.WriteLine($"New CollisionBspResource resource index = {Definition.CollisionBspResource.Page.Index:X4}; {Definition.CollisionBspResource.Page.Index:D4}"); break; case "pathfindingresource": Definition.PathfindingResource.ChangeLocation(resourceLocation); CacheContext.AddResource(Definition.PathfindingResource, stream); Console.WriteLine($"New PathfindingResource resource index = {Definition.PathfindingResource.Page.Index:X4}; {Definition.PathfindingResource.Page.Index:D4}"); break; default: Console.WriteLine("ERROR: Unrecognized resource type"); return(false); } Console.WriteLine("Done."); } return(true); }
public static void Populate(CommandContext commandContext, HaloOnlineCacheContext cacheContext, CachedTagInstance tag, ScenarioStructureBsp bsp) { commandContext.AddCommand(new CollisionTestCommand(cacheContext, tag, bsp)); commandContext.AddCommand(new ResourceDataCommand(cacheContext, tag, bsp)); commandContext.AddCommand(new ExtractCollisionGeometryCommand(cacheContext, bsp)); commandContext.AddCommand(new ExtractRenderGeometryCommand(cacheContext, bsp)); commandContext.AddCommand(new DumpRenderGeometryCommand(cacheContext, bsp.Geometry, "Decorator")); commandContext.AddCommand(new DumpRenderGeometryCommand(cacheContext, bsp.Geometry2, "Bsp")); commandContext.AddCommand(new DumpMoppCommand(cacheContext, bsp)); commandContext.AddCommand(new MoppDataCommand(cacheContext, bsp)); }
private ScenarioStructureBsp ConvertScenarioStructureBsp(ScenarioStructureBsp sbsp, CachedTag instance, Dictionary <ResourceLocation, Stream> resourceStreams) { var converter = new RenderGeometryConverter(CacheContext, BlamCache); // should be made static var blamDecoratorResourceDefinition = BlamCache.ResourceCache.GetRenderGeometryApiResourceDefinition(sbsp.DecoratorGeometry.Resource); var blamGeometryResourceDefinition = BlamCache.ResourceCache.GetRenderGeometryApiResourceDefinition(sbsp.Geometry.Resource); var decoratorGeometry = converter.Convert(sbsp.DecoratorGeometry, blamDecoratorResourceDefinition); var geometry = converter.Convert(sbsp.Geometry, blamGeometryResourceDefinition); foreach (var cluster in sbsp.Clusters) { List <ScenarioStructureBsp.Cluster.DecoratorGrid> newDecoratorGrids = new List <ScenarioStructureBsp.Cluster.DecoratorGrid>(); foreach (var grid in cluster.DecoratorGrids) { var buffer = blamDecoratorResourceDefinition.VertexBuffers[grid.Gen3Info.VertexBufferIndex].Definition; var offset = grid.VertexBufferOffset; grid.Vertices = new List <TinyPositionVertex>(); using (var stream = new MemoryStream(buffer.Data.Data)) { var vertexStream = VertexStreamFactory.Create(BlamCache.Version, stream); stream.Position = offset; for (int i = 0; i < grid.Amount; i++) { grid.Vertices.Add(vertexStream.ReadTinyPositionVertex()); } } if (grid.Amount == 0) { newDecoratorGrids.Add(grid); } else { // Get the new grids var newGrids = ConvertDecoratorGrid(grid.Vertices, grid); // Add all to list foreach (var newGrid in newGrids) { newDecoratorGrids.Add(newGrid); } } } cluster.DecoratorGrids = newDecoratorGrids; } // convert all the decorator vertex buffers foreach (var d3dBuffer in blamDecoratorResourceDefinition.VertexBuffers) { VertexBufferConverter.ConvertVertexBuffer(BlamCache.Version, CacheContext.Version, d3dBuffer.Definition); decoratorGeometry.VertexBuffers.Add(d3dBuffer); } sbsp.DecoratorGeometry.Resource = CacheContext.ResourceCache.CreateRenderGeometryApiResource(decoratorGeometry); sbsp.Geometry.Resource = CacheContext.ResourceCache.CreateRenderGeometryApiResource(geometry); sbsp.CollisionBspResource = ConvertStructureBspTagResources(sbsp); sbsp.PathfindingResource = ConvertStructureBspCacheFileTagResources(sbsp); sbsp.Unknown86 = 1; // // Set compatibility flag for H3 mopps for the engine to perform some fixups just in time // if (BlamCache.Version == CacheVersion.Halo3Retail || BlamCache.Version == CacheVersion.Halo3Beta) { sbsp.CompatibilityFlags |= ScenarioStructureBsp.StructureBspCompatibilityValue.UseMoppIndexPatch; } // // Temporary Fixes: // // Without this 005_intro crash on cortana sbsp sbsp.Geometry.MeshClusterVisibility = new List <RenderGeometry.MoppClusterVisiblity>(); return(sbsp); }
private PageableResource ConvertStructureBspCacheFileTagResources(ScenarioStructureBsp bsp, Dictionary <ResourceLocation, Stream> resourceStreams) { // // Set up ElDorado resource reference // bsp.PathfindingResource = new PageableResource { Page = new RawPage { Index = -1 }, Resource = new TagResourceGen3 { ResourceType = TagResourceTypeGen3.Pathfinding, DefinitionData = new byte[0x30], DefinitionAddress = new CacheResourceAddress(CacheResourceAddressType.Definition, 0), ResourceFixups = new List <TagResourceGen3.ResourceFixup>(), ResourceDefinitionFixups = new List <TagResourceGen3.ResourceDefinitionFixup>(), Unknown2 = 1 } }; // // Load Blam resource data // var resourceData = BlamCache.Version > CacheVersion.Halo3Retail ? BlamCache.GetRawFromID(bsp.ZoneAssetIndex4) : null; if (resourceData == null) { if (BlamCache.Version >= CacheVersion.Halo3ODST) { return(bsp.PathfindingResource); } resourceData = new byte[0x30]; } // // Port Blam resource definition // StructureBspCacheFileTagResources resourceDefinition = null; if (BlamCache.Version >= CacheVersion.Halo3ODST) { var resourceEntry = BlamCache.ResourceGestalt.TagResources[bsp.ZoneAssetIndex4.Index]; bsp.PathfindingResource.Resource.DefinitionAddress = resourceEntry.DefinitionAddress; bsp.PathfindingResource.Resource.DefinitionData = BlamCache.ResourceGestalt.FixupInformation.Skip(resourceEntry.FixupInformationOffset).Take(resourceEntry.FixupInformationLength).ToArray(); using (var definitionStream = new MemoryStream(bsp.PathfindingResource.Resource.DefinitionData, true)) using (var definitionReader = new EndianReader(definitionStream, EndianFormat.BigEndian)) using (var definitionWriter = new EndianWriter(definitionStream, EndianFormat.BigEndian)) { foreach (var fixup in resourceEntry.ResourceFixups) { var newFixup = new TagResourceGen3.ResourceFixup { BlockOffset = (uint)fixup.BlockOffset, Address = new CacheResourceAddress( fixup.Type == 4 ? CacheResourceAddressType.Resource : CacheResourceAddressType.Definition, fixup.Offset) }; definitionStream.Position = newFixup.BlockOffset; definitionWriter.Write(newFixup.Address.Value); bsp.PathfindingResource.Resource.ResourceFixups.Add(newFixup); } var dataContext = new DataSerializationContext(definitionReader, definitionWriter, CacheResourceAddressType.Definition); definitionStream.Position = bsp.PathfindingResource.Resource.DefinitionAddress.Offset; resourceDefinition = BlamCache.Deserializer.Deserialize <StructureBspCacheFileTagResources>(dataContext); } } else { resourceDefinition = new StructureBspCacheFileTagResources() { SurfacePlanes = new TagBlock <ScenarioStructureBsp.SurfacesPlanes>(bsp.SurfacePlanes.Count, new CacheResourceAddress()), Planes = new TagBlock <ScenarioStructureBsp.Plane>(bsp.Planes.Count, new CacheResourceAddress()), EdgeToSeams = new TagBlock <ScenarioStructureBsp.EdgeToSeamMapping>(bsp.EdgeToSeams.Count, new CacheResourceAddress()), PathfindingData = new List <StructureBspCacheFileTagResources.PathfindingDatum>() // TODO: copy from bsp.PathfindingData... }; } // // Port Blam resource to ElDorado resource cache // using (var blamResourceStream = new MemoryStream(resourceData)) using (var resourceReader = new EndianReader(blamResourceStream, EndianFormat.BigEndian)) using (var dataStream = new MemoryStream()) using (var resourceWriter = new EndianWriter(dataStream, EndianFormat.LittleEndian)) { var dataContext = new DataSerializationContext(resourceReader, resourceWriter); // // Surfaces Planes // StreamUtil.Align(dataStream, 0x4); if (BlamCache.Version >= CacheVersion.Halo3ODST) { blamResourceStream.Position = resourceDefinition.SurfacePlanes.Address.Offset; } resourceDefinition.SurfacePlanes = new TagBlock <ScenarioStructureBsp.SurfacesPlanes>( (BlamCache.Version < CacheVersion.Halo3ODST ? bsp.SurfacePlanes.Count : resourceDefinition.SurfacePlanes.Count), new CacheResourceAddress(CacheResourceAddressType.Resource, (int)dataStream.Position)); for (var i = 0; i < resourceDefinition.SurfacePlanes.Count; i++) { var element = BlamCache.Version < CacheVersion.Halo3ODST ? bsp.SurfacePlanes[i] : BlamCache.Deserializer.Deserialize <ScenarioStructureBsp.SurfacesPlanes>(dataContext); if (BlamCache.Version < CacheVersion.Halo3ODST) { element.PlaneIndexNew = element.PlaneIndexOld; element.PlaneCountNew = element.PlaneCountOld; } CacheContext.Serializer.Serialize(dataContext, element); } // // UnknownRaw1sts // StreamUtil.Align(dataStream, 0x4); if (BlamCache.Version >= CacheVersion.Halo3ODST) { blamResourceStream.Position = resourceDefinition.Planes.Address.Offset; } resourceDefinition.Planes = new TagBlock <ScenarioStructureBsp.Plane>( (BlamCache.Version < CacheVersion.Halo3ODST ? bsp.Planes.Count : resourceDefinition.Planes.Count), new CacheResourceAddress(CacheResourceAddressType.Resource, (int)dataStream.Position)); for (var i = 0; i < resourceDefinition.Planes.Count; i++) { var element = BlamCache.Version < CacheVersion.Halo3ODST ? bsp.Planes[i] : BlamCache.Deserializer.Deserialize <ScenarioStructureBsp.Plane>(dataContext); CacheContext.Serializer.Serialize(dataContext, element); } // // UnknownRaw7ths // StreamUtil.Align(dataStream, 0x4); if (BlamCache.Version >= CacheVersion.Halo3ODST) { blamResourceStream.Position = resourceDefinition.EdgeToSeams.Address.Offset; } resourceDefinition.EdgeToSeams = new TagBlock <ScenarioStructureBsp.EdgeToSeamMapping>( (BlamCache.Version < CacheVersion.Halo3ODST ? bsp.EdgeToSeams.Count : resourceDefinition.EdgeToSeams.Count), new CacheResourceAddress(CacheResourceAddressType.Resource, (int)dataStream.Position)); for (var i = 0; i < resourceDefinition.EdgeToSeams.Count; i++) { var element = BlamCache.Version < CacheVersion.Halo3ODST ? bsp.EdgeToSeams[i] : BlamCache.Deserializer.Deserialize <ScenarioStructureBsp.EdgeToSeamMapping>(dataContext); CacheContext.Serializer.Serialize(dataContext, element); } if (BlamCache.Version < CacheVersion.Halo3ODST && bsp.PathfindingData.Count != 0) { var pathfinding = new StructureBspCacheFileTagResources.PathfindingDatum() { StructureChecksum = bsp.PathfindingData[0].StructureChecksum, ObjectReferences = new List <StructureBspCacheFileTagResources.PathfindingDatum.ObjectReference>(), Seams = new List <StructureBspCacheFileTagResources.PathfindingDatum.Seam>(), JumpSeams = new List <StructureBspCacheFileTagResources.PathfindingDatum.JumpSeam>() }; foreach (var oldObjectReference in bsp.PathfindingData[0].ObjectReferences) { var objectReference = new StructureBspCacheFileTagResources.PathfindingDatum.ObjectReference { Flags = oldObjectReference.Flags, Bsps = new List <StructureBspCacheFileTagResources.PathfindingDatum.ObjectReference.BspReference>(), ObjectUniqueID = oldObjectReference.ObjectUniqueID, OriginBspIndex = oldObjectReference.OriginBspIndex, ObjectType = oldObjectReference.ObjectType.DeepClone(), Source = oldObjectReference.Source }; foreach (var bspRef in oldObjectReference.Bsps) { objectReference.Bsps.Add(new StructureBspCacheFileTagResources.PathfindingDatum.ObjectReference.BspReference { BspIndex = bspRef.BspIndex, NodeIndex = bspRef.NodeIndex, Bsp2dRefs = new TagBlock <ScenarioStructureBsp.PathfindingDatum.ObjectReference.BspReference.Bsp2dRef>(bspRef.Bsp2dRefs.Count, new CacheResourceAddress()), VertexOffset = bspRef.VertexOffset }); } pathfinding.ObjectReferences.Add(objectReference); } foreach (var oldSeam in bsp.PathfindingData[0].Seams) { pathfinding.Seams.Add(new StructureBspCacheFileTagResources.PathfindingDatum.Seam { LinkIndices = new TagBlock <ScenarioStructureBsp.PathfindingDatum.Seam.LinkIndexBlock>( oldSeam.LinkIndices.Count, new CacheResourceAddress()) }); } foreach (var oldJumpSeam in bsp.PathfindingData[0].JumpSeams) { pathfinding.JumpSeams.Add(new StructureBspCacheFileTagResources.PathfindingDatum.JumpSeam { UserJumpIndex = oldJumpSeam.UserJumpIndex, DestOnly = oldJumpSeam.DestOnly, Length = oldJumpSeam.Length, JumpIndices = new TagBlock <ScenarioStructureBsp.PathfindingDatum.JumpSeam.JumpIndexBlock>( oldJumpSeam.JumpIndices.Count, new CacheResourceAddress()) }); } resourceDefinition.PathfindingData.Add(pathfinding); } foreach (var pathfindingDatum in resourceDefinition.PathfindingData) { StreamUtil.Align(dataStream, 0x4); if (BlamCache.Version >= CacheVersion.Halo3ODST) { blamResourceStream.Position = pathfindingDatum.Sectors.Address.Offset; } pathfindingDatum.Sectors = new TagBlock <ScenarioStructureBsp.PathfindingDatum.Sector>( (BlamCache.Version < CacheVersion.Halo3ODST ? bsp.PathfindingData[0].Sectors.Count : pathfindingDatum.Sectors.Count), new CacheResourceAddress(CacheResourceAddressType.Resource, (int)dataStream.Position)); for (var i = 0; i < pathfindingDatum.Sectors.Count; i++) { CacheContext.Serializer.Serialize(dataContext, BlamCache.Version < CacheVersion.Halo3ODST ? bsp.PathfindingData[0].Sectors[i] : BlamCache.Deserializer.Deserialize <ScenarioStructureBsp.PathfindingDatum.Sector>(dataContext)); } StreamUtil.Align(dataStream, 0x4); if (BlamCache.Version >= CacheVersion.Halo3ODST) { blamResourceStream.Position = pathfindingDatum.Links.Address.Offset; } pathfindingDatum.Links = new TagBlock <ScenarioStructureBsp.PathfindingDatum.Link>( (BlamCache.Version < CacheVersion.Halo3ODST ? bsp.PathfindingData[0].Links.Count : pathfindingDatum.Links.Count), new CacheResourceAddress(CacheResourceAddressType.Resource, (int)dataStream.Position)); for (var i = 0; i < pathfindingDatum.Links.Count; i++) { CacheContext.Serializer.Serialize(dataContext, BlamCache.Version < CacheVersion.Halo3ODST ? bsp.PathfindingData[0].Links[i] : BlamCache.Deserializer.Deserialize <ScenarioStructureBsp.PathfindingDatum.Link>(dataContext)); } StreamUtil.Align(dataStream, 0x4); if (BlamCache.Version >= CacheVersion.Halo3ODST) { blamResourceStream.Position = pathfindingDatum.References.Address.Offset; } pathfindingDatum.References = new TagBlock <ScenarioStructureBsp.PathfindingDatum.Reference>( (BlamCache.Version < CacheVersion.Halo3ODST ? bsp.PathfindingData[0].References.Count : pathfindingDatum.References.Count), new CacheResourceAddress(CacheResourceAddressType.Resource, (int)dataStream.Position)); for (var i = 0; i < pathfindingDatum.References.Count; i++) { CacheContext.Serializer.Serialize(dataContext, BlamCache.Version < CacheVersion.Halo3ODST ? bsp.PathfindingData[0].References[i] : BlamCache.Deserializer.Deserialize <ScenarioStructureBsp.PathfindingDatum.Reference>(dataContext)); } StreamUtil.Align(dataStream, 0x4); if (BlamCache.Version >= CacheVersion.Halo3ODST) { blamResourceStream.Position = pathfindingDatum.Bsp2dNodes.Address.Offset; } pathfindingDatum.Bsp2dNodes = new TagBlock <ScenarioStructureBsp.PathfindingDatum.Bsp2dNode>( (BlamCache.Version < CacheVersion.Halo3ODST ? bsp.PathfindingData[0].Bsp2dNodes.Count : pathfindingDatum.Bsp2dNodes.Count), new CacheResourceAddress(CacheResourceAddressType.Resource, (int)dataStream.Position)); for (var i = 0; i < pathfindingDatum.Bsp2dNodes.Count; i++) { CacheContext.Serializer.Serialize(dataContext, BlamCache.Version < CacheVersion.Halo3ODST ? bsp.PathfindingData[0].Bsp2dNodes[i] : BlamCache.Deserializer.Deserialize <ScenarioStructureBsp.PathfindingDatum.Bsp2dNode>(dataContext)); } StreamUtil.Align(dataStream, 0x4); if (BlamCache.Version >= CacheVersion.Halo3ODST) { blamResourceStream.Position = pathfindingDatum.Vertices.Address.Offset; } pathfindingDatum.Vertices = new TagBlock <ScenarioStructureBsp.PathfindingDatum.Vertex>( (BlamCache.Version < CacheVersion.Halo3ODST ? bsp.PathfindingData[0].Vertices.Count : pathfindingDatum.Vertices.Count), new CacheResourceAddress(CacheResourceAddressType.Resource, (int)dataStream.Position)); for (var i = 0; i < pathfindingDatum.Vertices.Count; i++) { CacheContext.Serializer.Serialize(dataContext, BlamCache.Version < CacheVersion.Halo3ODST ? bsp.PathfindingData[0].Vertices[i] : BlamCache.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]; StreamUtil.Align(dataStream, 0x4); if (BlamCache.Version >= CacheVersion.Halo3ODST) { blamResourceStream.Position = bspRef.Bsp2dRefs.Address.Offset; } bspRef.Bsp2dRefs.Address = new CacheResourceAddress(CacheResourceAddressType.Resource, (int)dataStream.Position); for (var bsp2dRefIdx = 0; bsp2dRefIdx < bspRef.Bsp2dRefs.Count; bsp2dRefIdx++) { var bsp2dRef = BlamCache.Version < CacheVersion.Halo3ODST ? bsp.PathfindingData[0].ObjectReferences[objRefIdx].Bsps[bspRefIdx].Bsp2dRefs[bsp2dRefIdx] : BlamCache.Deserializer.Deserialize <ScenarioStructureBsp.PathfindingDatum.ObjectReference.BspReference.Bsp2dRef>(dataContext); CacheContext.Serializer.Serialize(dataContext, bsp2dRef); } } } StreamUtil.Align(dataStream, 0x4); if (BlamCache.Version >= CacheVersion.Halo3ODST) { blamResourceStream.Position = pathfindingDatum.PathfindingHints.Address.Offset; } pathfindingDatum.PathfindingHints = new TagBlock <ScenarioStructureBsp.PathfindingDatum.PathfindingHint>( (BlamCache.Version < CacheVersion.Halo3ODST ? bsp.PathfindingData[0].PathfindingHints.Count : pathfindingDatum.PathfindingHints.Count), new CacheResourceAddress(CacheResourceAddressType.Resource, (int)dataStream.Position)); for (var i = 0; i < pathfindingDatum.PathfindingHints.Count; i++) { var hint = BlamCache.Version < CacheVersion.Halo3ODST ? bsp.PathfindingData[0].PathfindingHints[i] : BlamCache.Deserializer.Deserialize <ScenarioStructureBsp.PathfindingDatum.PathfindingHint>(dataContext); if (BlamCache.Version < CacheVersion.Halo3ODST && (hint.HintType == JumpLink || hint.HintType == WallJumpLink)) { hint.Data[3] = (hint.Data[3] & ~ushort.MaxValue) | ((hint.Data[2] >> 16) & ushort.MaxValue); hint.Data[2] = (hint.Data[2] & ~(ushort.MaxValue << 16)); //remove old landing sector hint.Data[2] = (hint.Data[2] | ((hint.Data[2] & (byte.MaxValue << 8)) << 8)); //move jump height flags hint.Data[2] = (hint.Data[2] & ~(byte.MaxValue << 8)); //remove old flags } CacheContext.Serializer.Serialize(dataContext, hint); } StreamUtil.Align(dataStream, 0x4); if (BlamCache.Version >= CacheVersion.Halo3ODST) { blamResourceStream.Position = pathfindingDatum.InstancedGeometryReferences.Address.Offset; } pathfindingDatum.InstancedGeometryReferences = new TagBlock <ScenarioStructureBsp.PathfindingDatum.InstancedGeometryReference>( (BlamCache.Version < CacheVersion.Halo3ODST ? bsp.PathfindingData[0].InstancedGeometryReferences.Count : pathfindingDatum.InstancedGeometryReferences.Count), new CacheResourceAddress(CacheResourceAddressType.Resource, (int)dataStream.Position)); for (var i = 0; i < pathfindingDatum.InstancedGeometryReferences.Count; i++) { CacheContext.Serializer.Serialize(dataContext, BlamCache.Version < CacheVersion.Halo3ODST ? bsp.PathfindingData[0].InstancedGeometryReferences[i] : BlamCache.Deserializer.Deserialize <ScenarioStructureBsp.PathfindingDatum.InstancedGeometryReference>(dataContext)); } StreamUtil.Align(dataStream, 0x4); if (BlamCache.Version >= CacheVersion.Halo3ODST) { blamResourceStream.Position = pathfindingDatum.GiantPathfinding.Address.Offset; } pathfindingDatum.GiantPathfinding = new TagBlock <ScenarioStructureBsp.PathfindingDatum.GiantPathfindingBlock>( (BlamCache.Version < CacheVersion.Halo3ODST ? bsp.PathfindingData[0].GiantPathfinding.Count : pathfindingDatum.GiantPathfinding.Count), new CacheResourceAddress(CacheResourceAddressType.Resource, (int)dataStream.Position)); for (var i = 0; i < pathfindingDatum.GiantPathfinding.Count; i++) { CacheContext.Serializer.Serialize(dataContext, BlamCache.Version < CacheVersion.Halo3ODST ? bsp.PathfindingData[0].GiantPathfinding[i] : BlamCache.Deserializer.Deserialize <ScenarioStructureBsp.PathfindingDatum.GiantPathfindingBlock>(dataContext)); } for (var unk2Idx = 0; unk2Idx < pathfindingDatum.Seams.Count; unk2Idx++) { var unknown2 = pathfindingDatum.Seams[unk2Idx]; StreamUtil.Align(dataStream, 0x4); if (BlamCache.Version >= CacheVersion.Halo3ODST) { blamResourceStream.Position = unknown2.LinkIndices.Address.Offset; } unknown2.LinkIndices = new TagBlock <ScenarioStructureBsp.PathfindingDatum.Seam.LinkIndexBlock>( (BlamCache.Version < CacheVersion.Halo3ODST ? bsp.PathfindingData[0].Seams[unk2Idx].LinkIndices.Count : unknown2.LinkIndices.Count), new CacheResourceAddress(CacheResourceAddressType.Resource, (int)dataStream.Position)); for (var unkIdx = 0; unkIdx < unknown2.LinkIndices.Count; unkIdx++) { CacheContext.Serializer.Serialize(dataContext, BlamCache.Version < CacheVersion.Halo3ODST ? bsp.PathfindingData[0].Seams[unk2Idx].LinkIndices[unkIdx] : BlamCache.Deserializer.Deserialize <ScenarioStructureBsp.PathfindingDatum.Seam.LinkIndexBlock>(dataContext)); } } for (var unk3Idx = 0; unk3Idx < pathfindingDatum.JumpSeams.Count; unk3Idx++) { var unknown3 = pathfindingDatum.JumpSeams[unk3Idx]; StreamUtil.Align(dataStream, 0x4); if (BlamCache.Version >= CacheVersion.Halo3ODST) { blamResourceStream.Position = unknown3.JumpIndices.Address.Offset; } unknown3.JumpIndices = new TagBlock <ScenarioStructureBsp.PathfindingDatum.JumpSeam.JumpIndexBlock>( (BlamCache.Version < CacheVersion.Halo3ODST ? bsp.PathfindingData[0].JumpSeams[unk3Idx].JumpIndices.Count : unknown3.JumpIndices.Count), new CacheResourceAddress(CacheResourceAddressType.Resource, (int)dataStream.Position)); for (var unk4Idx = 0; unk4Idx < unknown3.JumpIndices.Count; unk4Idx++) { CacheContext.Serializer.Serialize(dataContext, BlamCache.Version < CacheVersion.Halo3ODST ? bsp.PathfindingData[0].JumpSeams[unk3Idx].JumpIndices[unk4Idx] : BlamCache.Deserializer.Deserialize <ScenarioStructureBsp.PathfindingDatum.JumpSeam.JumpIndexBlock>(dataContext)); } } StreamUtil.Align(dataStream, 0x4); if (BlamCache.Version >= CacheVersion.Halo3ODST) { blamResourceStream.Position = pathfindingDatum.Doors.Address.Offset; } pathfindingDatum.Doors = new TagBlock <ScenarioStructureBsp.PathfindingDatum.Door>( (BlamCache.Version < CacheVersion.Halo3ODST ? bsp.PathfindingData[0].Doors.Count : pathfindingDatum.Doors.Count), new CacheResourceAddress(CacheResourceAddressType.Resource, (int)dataStream.Position)); for (var i = 0; i < pathfindingDatum.Doors.Count; i++) { CacheContext.Serializer.Serialize(dataContext, BlamCache.Version < CacheVersion.Halo3ODST ? bsp.PathfindingData[0].Doors[i] : BlamCache.Deserializer.Deserialize <ScenarioStructureBsp.PathfindingDatum.Door>(dataContext)); } } CacheContext.Serializer.Serialize(new ResourceSerializationContext(CacheContext, bsp.PathfindingResource), resourceDefinition); resourceWriter.BaseStream.Position = 0; dataStream.Position = 0; bsp.PathfindingResource.ChangeLocation(ResourceLocation.ResourcesB); var resource = bsp.PathfindingResource; if (resource == null) { throw new ArgumentNullException("resource"); } if (!dataStream.CanRead) { throw new ArgumentException("The input stream is not open for reading", "dataStream"); } var cache = CacheContext.GetResourceCache(ResourceLocation.ResourcesB); if (!resourceStreams.ContainsKey(ResourceLocation.ResourcesB)) { resourceStreams[ResourceLocation.ResourcesB] = FlagIsSet(PortingFlags.Memory) ? new MemoryStream() : (Stream)CacheContext.OpenResourceCacheReadWrite(ResourceLocation.ResourcesB); if (FlagIsSet(PortingFlags.Memory)) { using (var resourceStream = CacheContext.OpenResourceCacheRead(ResourceLocation.ResourcesB)) resourceStream.CopyTo(resourceStreams[ResourceLocation.ResourcesB]); } } var dataSize = (int)(dataStream.Length - dataStream.Position); var data = new byte[dataSize]; dataStream.Read(data, 0, dataSize); resource.Page.Index = cache.Add(resourceStreams[ResourceLocation.ResourcesB], data, out uint compressedSize); resource.Page.CompressedBlockSize = compressedSize; resource.Page.UncompressedBlockSize = (uint)dataSize; resource.DisableChecksum(); } if (BlamCache.Version < CacheVersion.Halo3ODST) { bsp.SurfacePlanes.Clear(); bsp.Planes.Clear(); bsp.EdgeToSeams.Clear(); bsp.PathfindingData.Clear(); } return(bsp.PathfindingResource); }
private TagResourceReference ConvertStructureBspCacheFileTagResources(ScenarioStructureBsp bsp) { // // Set up ElDorado resource reference // if (BlamCache.Version < CacheVersion.Halo3ODST) { bsp.PathfindingResource = new TagResourceReference(); } // // Load Blam resource data // var resourceDefinition = BlamCache.Version > CacheVersion.Halo3Retail ? BlamCache.ResourceCache.GetStructureBspCacheFileTagResources(bsp.PathfindingResource) : null; if (resourceDefinition == null && BlamCache.Version >= CacheVersion.Halo3ODST) { return(bsp.PathfindingResource); } // // Port Blam resource definition // if (BlamCache.Version < CacheVersion.Halo3ODST) { resourceDefinition = new StructureBspCacheFileTagResources() { SurfacePlanes = new TagBlock <SurfacesPlanes>(CacheAddressType.Data, bsp.SurfacePlanes), Planes = new TagBlock <PlaneReference>(CacheAddressType.Data, bsp.Planes), EdgeToSeams = new TagBlock <EdgeToSeamMapping>(CacheAddressType.Data, bsp.EdgeToSeams), PathfindingData = new TagBlock <ResourcePathfinding>(CacheAddressType.Definition) }; foreach (var pathfinding in bsp.PathfindingData) { resourceDefinition.PathfindingData.Add(PathfindingConverter.CreateResourcePathfindingFromTag(pathfinding)); } // convert hints foreach (var pathfindingDatum in resourceDefinition.PathfindingData) { foreach (var hint in pathfindingDatum.PathfindingHints) { if (hint.HintType == PathfindingHint.HintTypeValue.JumpLink || hint.HintType == PathfindingHint.HintTypeValue.WallJumpLink) { hint.Data[3] = (hint.Data[3] & ~ushort.MaxValue) | ((hint.Data[2] >> 16) & ushort.MaxValue); hint.Data[2] = (hint.Data[2] & ~(ushort.MaxValue << 16)); //remove old landing sector hint.Data[2] = (hint.Data[2] | ((hint.Data[2] & (byte.MaxValue << 8)) << 8)); //move jump height flags hint.Data[2] = (hint.Data[2] & ~(byte.MaxValue << 8)); //remove old flags } } } // fix surface planes foreach (var surfacePlane in resourceDefinition.SurfacePlanes) { surfacePlane.PlaneCountNew = surfacePlane.PlaneCountOld; surfacePlane.PlaneIndexNew = surfacePlane.PlaneIndexOld; } } bsp.PathfindingResource = CacheContext.ResourceCache.CreateStructureBspCacheFileResource(resourceDefinition); if (BlamCache.Version < CacheVersion.Halo3ODST) { bsp.SurfacePlanes.Clear(); bsp.Planes.Clear(); bsp.EdgeToSeams.Clear(); bsp.PathfindingData.Clear(); } return(bsp.PathfindingResource); }
public static CommandContext Create(CommandContext parent, GameCache cache, CachedTag tag, ScenarioStructureBsp bsp) { var groupName = cache.StringTable.GetString(tag.Group.Name); var context = new CommandContext(parent, string.Format("{0:X8}.{1}", tag.Index, groupName)); Populate(context, cache, tag, bsp); return(context); }
public static void Populate(CommandContext commandContext, GameCache cache, CachedTag tag, ScenarioStructureBsp bsp) { commandContext.AddCommand(new GenerateJumpHintsCommand(cache, tag, bsp)); commandContext.AddCommand(new DumpRenderGeometryCommand(cache, bsp.DecoratorGeometry, "Decorator")); commandContext.AddCommand(new DumpRenderGeometryCommand(cache, bsp.Geometry, "Bsp")); commandContext.AddCommand(new MoppDataCommand(bsp)); commandContext.AddCommand(new ExtractCollisionGeometryCommand(cache, bsp)); commandContext.AddCommand(new ExtractPathfindingGeometryCommand(cache, bsp)); commandContext.AddCommand(new ExtractRenderGeometryCommand(cache, bsp)); }
private static bool ExtractResource(ScenarioStructureBsp Definition, HaloOnlineCacheContext CacheContext, IReadOnlyList <string> args) { if (args.Count < 1) { return(false); } var resourceType = ""; var filePath = ""; var cachePath = "resources.dat"; resourceType = args[1].ToLower(); // geometry2 filePath = args[2]; // sc140_000_geometry2.raw PageableResource resource = null; switch (resourceType) { case "geometry": resource = Definition.Geometry.Resource; break; case "geometry2": resource = Definition.Geometry2.Resource; break; case "collisionbspresource": resource = Definition.CollisionBspResource; break; case "pathfindingresource": resource = Definition.PathfindingResource; break; default: Console.WriteLine($"Invalid sbsp resource type."); return(false); } if (resource == null || resource.Page.Index < 0 || !resource.GetLocation(out var location)) { Console.WriteLine("Resource is null."); return(false); } try { using (var stream = File.OpenRead(CacheContext.TagCacheFile.DirectoryName + "\\" + cachePath)) { var cache = new ResourceCache(stream); using (var outStream = File.Open(filePath, FileMode.Create, FileAccess.Write)) { cache.Decompress(stream, resource.Page.Index, resource.Page.CompressedBlockSize, outStream); Console.WriteLine("Wrote 0x{0:X} bytes to {1}.", outStream.Position, filePath); } } } catch (Exception ex) { Console.WriteLine("Failed to extract resource: {0}", ex.Message); } return(true); }
private ScenarioStructureBsp ConvertScenarioStructureBsp(ScenarioStructureBsp sbsp, CachedTagInstance instance, Dictionary <ResourceLocation, Stream> resourceStreams) { sbsp.CollisionBspResource = ConvertStructureBspTagResources(sbsp, resourceStreams); sbsp.PathfindingResource = ConvertStructureBspCacheFileTagResources(sbsp, resourceStreams); sbsp.Unknown86 = 1; // // Set compatibility flag for H3 mopps // if (BlamCache.Version == CacheVersion.Halo3Retail) { sbsp.CompatibilityFlags = ScenarioStructureBsp.StructureBspCompatibilityValue.UseMoppIndexPatch; } else { sbsp.CompatibilityFlags = ScenarioStructureBsp.StructureBspCompatibilityValue.None; } // // Fix cluster tag ref and decorator grids // var resource = sbsp.Geometry.Resource; if (resource != null && resource.Page.Index >= 0 && resource.GetLocation(out var location)) { var resourceContext = new ResourceSerializationContext(CacheContext, sbsp.Geometry.Resource); var definition = CacheContext.Deserializer.Deserialize <RenderGeometryApiResourceDefinition>(resourceContext); using (var edResourceStream = new MemoryStream()) using (var edResourceReader = new EndianReader(edResourceStream, EndianFormat.LittleEndian)) { var pageable = sbsp.Geometry.Resource; if (pageable == null) { throw new ArgumentNullException("sbsp.Geometry.Resource"); } if (!edResourceStream.CanWrite) { throw new ArgumentException("The output stream is not open for writing", "outStream"); } pageable.GetLocation(out var resourceLocation); var cache = CacheContext.GetResourceCache(resourceLocation); if (!resourceStreams.ContainsKey(resourceLocation)) { resourceStreams[resourceLocation] = FlagIsSet(PortingFlags.Memory) ? new MemoryStream() : (Stream)CacheContext.OpenResourceCacheReadWrite(resourceLocation); if (FlagIsSet(PortingFlags.Memory)) { using (var resourceStream = CacheContext.OpenResourceCacheRead(resourceLocation)) resourceStream.CopyTo(resourceStreams[resourceLocation]); } } cache.Decompress(resourceStreams[resourceLocation], pageable.Page.Index, pageable.Page.CompressedBlockSize, edResourceStream); var inVertexStream = VertexStreamFactory.Create(CacheVersion.HaloOnline106708, edResourceStream); foreach (var cluster in sbsp.Clusters) { List <ScenarioStructureBsp.Cluster.DecoratorGrid> newDecoratorGrids = new List <ScenarioStructureBsp.Cluster.DecoratorGrid>(); foreach (var grid in cluster.DecoratorGrids) { grid.DecoratorGeometryIndex_HO = grid.DecoratorGeometryIndex_H3; grid.DecoratorIndex_HO = grid.DecoratorIndex_H3; if (grid.Amount == 0) { newDecoratorGrids.Add(grid); } else { List <TinyPositionVertex> vertices = new List <TinyPositionVertex>(); // Get the buffer the right grid var vertexBuffer = definition.VertexBuffers[grid.DecoratorGeometryIndex_HO].Definition; // Get the offset from the grid edResourceStream.Position = vertexBuffer.Data.Address.Offset + grid.DecoratorGeometryOffset; // Read all vertices and add to the list for (int i = 0; i < grid.Amount; i++) { vertices.Add(inVertexStream.ReadTinyPositionVertex()); } // Get the new grids List <ScenarioStructureBsp.Cluster.DecoratorGrid> newGrids = ConvertDecoratorGrid(vertices, grid); // Add all to list foreach (var newGrid in newGrids) { newDecoratorGrids.Add(newGrid); } } } cluster.DecoratorGrids = newDecoratorGrids; } } } // // Temporary Fixes: // // Without this 005_intro crash on cortana sbsp sbsp.Geometry2.UnknownSections = new List <RenderGeometry.UnknownSection>(); return(sbsp); }