public IGeometryModel ReadGeometry(int lod) { if (lod < 0 || lod >= ((IRenderGeometry)this).LodCount) { throw new ArgumentOutOfRangeException(nameof(lod)); } var model = new GeometryModel(Name) { CoordinateSystem = CoordinateSystem.Default }; model.Nodes.AddRange(Nodes); model.MarkerGroups.AddRange(MarkerGroups); model.Bounds.AddRange(BoundingBoxes); model.Materials.AddRange(HaloReachCommon.GetMaterials(Shaders)); foreach (var region in Regions) { var gRegion = new GeometryRegion { SourceIndex = Regions.IndexOf(region), Name = region.Name }; gRegion.Permutations.AddRange(region.Permutations.Where(p => p.SectionIndex >= 0).Select(p => new GeometryPermutation { SourceIndex = region.Permutations.IndexOf(p), Name = p.Name, MeshIndex = p.SectionIndex, MeshCount = 1 })); if (gRegion.Permutations.Any()) { model.Regions.Add(gRegion); } } Func <int, int, int> mapNodeFunc = null; if (Flags.HasFlag(ModelFlags.UseLocalNodes)) { mapNodeFunc = (si, i) => NodeMaps[si].Indices[i]; } model.Meshes.AddRange(HaloReachCommon.GetMeshes(cache, ResourcePointer, Sections, (s, m) => m.BoundsIndex = 0, mapNodeFunc)); CreateInstanceMeshes(model); return(model); }
public IGeometryModel ReadGeometry(int lod) { if (lod < 0 || lod >= ((IRenderGeometry)this).LodCount) { throw new ArgumentOutOfRangeException(nameof(lod)); } var scenario = cache.TagIndex.GetGlobalTag("scnr").ReadMetadata <scenario>(); var model = new GeometryModel(item.FileName()) { CoordinateSystem = CoordinateSystem.Default }; var bspBlock = scenario.StructureBsps.First(s => s.BspReference.TagId == item.Id); var bspIndex = scenario.StructureBsps.IndexOf(bspBlock); var lightmap = scenario.ScenarioLightmapReference.Tag.ReadMetadata <scenario_lightmap>(); var lightmapData = lightmap.LightmapRefs[bspIndex].LightmapDataReference.Tag.ReadMetadata <scenario_lightmap_bsp_data>(); model.Bounds.AddRange(BoundingBoxes); model.Materials.AddRange(HaloReachCommon.GetMaterials(Shaders)); var clusterRegion = new GeometryRegion { Name = "Clusters" }; clusterRegion.Permutations.AddRange( Clusters.Select((c, i) => new GeometryPermutation { SourceIndex = i, Name = Clusters.IndexOf(c).ToString("D3", CultureInfo.CurrentCulture), MeshIndex = c.SectionIndex, MeshCount = 1 }) ); model.Regions.Add(clusterRegion); if (cache.CacheType >= CacheType.HaloReachRetail && !loadedInstances) { var resourceGestalt = cache.TagIndex.GetGlobalTag("zone").ReadMetadata <cache_file_resource_gestalt>(); var entry = resourceGestalt.ResourceEntries[InstancesResourcePointer.ResourceIndex]; var address = entry.FixupOffset + entry.ResourceFixups[entry.ResourceFixups.Count - 10].Offset & 0x0FFFFFFF; using (var cacheReader = cache.CreateReader(cache.DefaultAddressTranslator)) using (var reader = cacheReader.CreateVirtualReader(resourceGestalt.FixupDataPointer.Address)) { for (int i = 0; i < GeometryInstances.Count; i++) { reader.Seek(address + 156 * i, SeekOrigin.Begin); GeometryInstances[i].TransformScale = reader.ReadSingle(); GeometryInstances[i].Transform = reader.ReadObject <Matrix4x4>(); reader.Seek(6, SeekOrigin.Current); GeometryInstances[i].SectionIndex = reader.ReadInt16(); } } loadedInstances = true; } foreach (var instanceGroup in GeometryInstances.GroupBy(i => i.SectionIndex)) { var section = lightmapData.Sections[instanceGroup.Key]; var sectionRegion = new GeometryRegion { Name = Utils.CurrentCulture($"Instances {instanceGroup.Key:D3}") }; sectionRegion.Permutations.AddRange( instanceGroup.Select(i => new GeometryPermutation { SourceIndex = GeometryInstances.IndexOf(i), Name = i.Name, Transform = i.Transform, TransformScale = i.TransformScale, MeshIndex = i.SectionIndex, MeshCount = 1 }) ); model.Regions.Add(sectionRegion); } model.Meshes.AddRange(HaloReachCommon.GetMeshes(cache, lightmapData.ResourcePointer, lightmapData.Sections, (s, m) => { var index = (short)lightmapData.Sections.IndexOf(s); m.BoundsIndex = index >= BoundingBoxes.Count ? (short?)null : index; m.IsInstancing = index < BoundingBoxes.Count; })); return(model); }