public RenderMaterial(Direct3D.Device device, GameCache cache, TagTool.Geometry.RenderMaterial material) { if (material.RenderMethod == null) { return; } using (var cacheStream = cache.OpenCacheRead()) { var renderMethod = cache.Deserialize <RenderMethod>(cacheStream, material.RenderMethod); var template = cache.Deserialize <RenderMethodTemplate>(cacheStream, renderMethod.ShaderProperties[0].Template); Textures = new Dictionary <string, RenderTexture>(); for (var shaderMapIndex = 0; shaderMapIndex < renderMethod.ShaderProperties[0].TextureConstants.Count; shaderMapIndex++) { var shaderMapName = cache.StringTable.GetString(template.TextureParameterNames[shaderMapIndex].Name); if (Textures.ContainsKey(shaderMapName)) { continue; } var shaderMap = renderMethod.ShaderProperties[0].TextureConstants[shaderMapIndex]; var shaderMapDefinition = cache.Deserialize <Bitmap>(cacheStream, shaderMap.Bitmap); Textures[shaderMapName] = new RenderTexture(device, cache, shaderMapDefinition, shaderMap.BitmapIndex); } } }
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 RenderMethod MatchShader(RenderMethod renderMethod) { if (renderMethod.ShaderProperties.Count < 0) { return(renderMethod); } var property = renderMethod.ShaderProperties[0]; var originalTemplate = PortingCache.Deserialize <RenderMethodTemplate>(PortingCacheStream, property.Template); var matchedTemplateTag = FindClosestTemplate(property.Template, originalTemplate); var matchedTemplate = BaseCache.Deserialize <RenderMethodTemplate>(BaseCacheStream, matchedTemplateTag); renderMethod = MatchRenderMethods(renderMethod, matchedTemplate, originalTemplate); // might require some special checks if match render method can fail return(renderMethod); }
public override object Execute(List <string> args) { if (args.Count < 1 || args.Count > 2) { return(false); } if (args[0] == "new") { return(MatchShaderNew(args[1])); } else if (args.Count == 2) { return(false); } RenderMethodTemplate bmRmt2 = new RenderMethodTemplate(); CachedTag bmRmt2Instance; using (var blamStream = BlamCache.OpenCacheRead()) { if (BlamCache.TryGetCachedTag(args[0], out bmRmt2Instance)) { bmRmt2 = BlamCache.Deserialize <RenderMethodTemplate>(blamStream, bmRmt2Instance); } else { return(false); } } List <string> bmMaps = new List <string>(); List <string> bmArgs = new List <string>(); // Get a simple list of H3 bitmaps and arguments names foreach (var a in bmRmt2.TextureParameterNames) { bmMaps.Add(BlamCache.StringTable.GetString(a.Name)); } foreach (var a in bmRmt2.RealParameterNames) { bmArgs.Add(BlamCache.StringTable.GetString(a.Name)); } string result = null; using (var cacheStream = Cache.OpenCacheRead()) { ShaderMatcher Matcher = new ShaderMatcher(); Matcher.Init(cacheStream, Cache, BlamCache); // Find a HO equivalent rmt2 var edRmt2Instance = Matcher.FixRmt2Reference(cacheStream, bmRmt2Instance.Name, bmRmt2Instance, bmRmt2, bmMaps, bmArgs); result = edRmt2Instance.Name; } Console.WriteLine($"Blam template \"{bmRmt2Instance.Name}.rmt2\"\n matched with \"{result}.rmt2\"."); return(true); }
private byte[] ConvertGen3SoundData(GameCache cache, Sound definition, byte[] soundData) { // todo: use PortingContextFactory here (currently inaccessible) SoundCacheFileGestalt blamSoundGestalt = null; foreach (var tag in cache.TagCache.TagTable) { if (tag.Group.Tag == "ugh!") { using (var stream = cache.OpenCacheRead()) blamSoundGestalt = cache.Deserialize <SoundCacheFileGestalt>(stream, tag); break; } } // ExportSoundCommand code using (MemoryStream soundDataStream = new MemoryStream()) { using (EndianWriter output = new EndianWriter(soundDataStream, EndianFormat.BigEndian)) { if (blamSoundGestalt != null) { for (int pitchRangeIndex = definition.SoundReference.PitchRangeIndex; pitchRangeIndex < definition.SoundReference.PitchRangeIndex + definition.SoundReference.PitchRangeCount; pitchRangeIndex++) { var relativePitchRangeIndex = pitchRangeIndex - definition.SoundReference.PitchRangeIndex; var permutationCount = blamSoundGestalt.GetPermutationCount(pitchRangeIndex); for (int i = 0; i < permutationCount; i++) { BlamSound blamSound = SoundConverter.ConvertGen3Sound(cache, blamSoundGestalt, definition, relativePitchRangeIndex, i, soundData); output.WriteBlock(blamSound.Data); } } } } return(soundDataStream.ToArray()); } }
public static SoundCacheFileGestalt LoadSoundGestalt(GameCache cache, Stream cacheStream) { CachedTag blamTag = null; foreach (var tag in cache.TagCache.TagTable) { if (tag.Group.Tag == "ugh!") { blamTag = tag; break; } } if (blamTag == null) { return(null); } SoundCacheFileGestalt result = cache.Deserialize <SoundCacheFileGestalt>(cacheStream, blamTag); return(result); }
public override object Execute(List <string> args) { var argStack = new Stack <string>(args.AsEnumerable().Reverse()); var portingFlags = ParsePortingFlags(argStack); if (argStack.Count < 1) { Console.WriteLine("ERROR: Expected bsp index!"); return(false); } var sbspIndex = int.Parse(argStack.Pop()); using (var blamCacheStream = BlamCache.OpenCacheRead()) using (var hoCacheStream = HoCache.OpenCacheReadWrite()) { var blamScnr = BlamCache.Deserialize <Scenario>(blamCacheStream, BlamCache.TagCache.FindFirstInGroup("scnr")); var blamSbsp = BlamCache.Deserialize <ScenarioStructureBsp>(blamCacheStream, blamScnr.StructureBsps[sbspIndex].StructureBsp); var desiredInstances = new Dictionary <int, string>(); if (argStack.Count > 0) { var identifier = argStack.Pop(); string desiredName = null; if (argStack.Count > 0) { desiredName = argStack.Pop(); } var index = FindBlockIndex(blamSbsp.Clusters, identifier); desiredInstances.Add(index, desiredName); } else { Console.WriteLine("------------------------------------------------------------------"); Console.WriteLine("Enter each cluster with the format <Index> [New tagname]"); Console.WriteLine("Enter a blank line to finish."); Console.WriteLine("------------------------------------------------------------------"); for (string line; !String.IsNullOrWhiteSpace(line = Console.ReadLine());) { var parts = line.Split(' '); var identifier = parts[0]; var name = parts.Length > 1 ? string.Join(" ", parts.Skip(1)) : null; var index = FindBlockIndex(blamSbsp.Clusters, identifier); if (index == -1) { Console.WriteLine($"ERROR: Instance not found by identifier {identifier}!"); return(false); } desiredInstances.Add(index, name); } } if (desiredInstances.Count < 1) { return(true); } var converter = new GeometryToObjectConverter(HoCache, hoCacheStream, BlamCache, blamCacheStream, blamScnr, sbspIndex); converter.PortTag.SetFlags(portingFlags); var forgTag = HoCache.TagCache.FindFirstInGroup("forg"); var forg = HoCache.Deserialize <ForgeGlobalsDefinition>(hoCacheStream, forgTag); var newTags = new List <CachedTag>(); foreach (var kv in desiredInstances) { try { var tag = converter.ConvertGeometry(kv.Key, kv.Value, true); forg.Palette.Add(new ForgeGlobalsDefinition.PaletteItem() { CategoryIndex = (short)1, DescriptionIndex = -1, Name = tag.Name, Object = tag, Type = ForgeGlobalsDefinition.PaletteItemType.Prop, Setters = new List <ForgeGlobalsDefinition.PaletteItem.Setter>() { new ForgeGlobalsDefinition.PaletteItem.Setter() { Target = ForgeGlobalsDefinition.PaletteItem.SetterTarget.General_Physics, IntegerValue = 1 // phased } } }); } finally { HoCache.SaveStrings(); HoCache.SaveTagNames(); } } HoCache.Serialize(hoCacheStream, forgTag, forg); } return(true); }
public RenderObject(D3DDevice device, GameCache cache, GameObject definition, RealPoint3d position, RealEulerAngles3d rotation) { if (device == null) { throw new ArgumentNullException(nameof(device)); } else if (cache == null) { throw new ArgumentNullException(nameof(cache)); } else if (definition == null) { throw new ArgumentNullException(nameof(definition)); } Device = device; Cache = cache; Object = definition; Position = position; Rotation = rotation; UpdateTransform(); using (var cacheStream = Cache.OpenCacheRead()) { if (Object.Model == null) { throw new NullReferenceException(nameof(Object.Model)); } Model = Cache.Deserialize <Model>(cacheStream, Object.Model); if (Model.RenderModel == null) { throw new NullReferenceException(nameof(Model.RenderModel)); } RenderModel = Cache.Deserialize <RenderModel>(cacheStream, Model.RenderModel); if (Model.Variants == null || Model.Variants.Count == 0) { var modelVariant = new Model.Variant { Name = Cache.StringTable.GetStringId("default"), Regions = new List <Model.Variant.Region>() }; foreach (var region in RenderModel.Regions) { var modelRegion = new Model.Variant.Region { Name = region.Name, RenderModelRegionIndex = (sbyte)RenderModel.Regions.IndexOf(region), Permutations = new List <Model.Variant.Region.Permutation>() }; foreach (var permutation in region.Permutations) { modelRegion.Permutations.Add(new Model.Variant.Region.Permutation { Name = modelVariant.Name, RenderModelPermutationIndex = (sbyte)region.Permutations.IndexOf(permutation) }); } modelVariant.Regions.Add(modelRegion); } Model.Variants = new List <Model.Variant> { modelVariant }; } Materials = new List <RenderMaterial>(); foreach (var material in RenderModel.Materials) { Materials.Add(new RenderMaterial(device, Cache, material)); } if (RenderModel.Geometry.Resource == null) { throw new NullReferenceException(nameof(RenderModel.Geometry.Resource)); } RenderGeometryResource = Cache.ResourceCache.GetRenderGeometryApiResourceDefinition(RenderModel.Geometry.Resource); VertexBuffers = new Dictionary <int, VertexBuffer>(); IndexBuffers = new Dictionary <int, IndexBuffer>(); var compression = RenderModel.Geometry.Compression[0]; foreach (var mesh in RenderModel.Geometry.Meshes) { var renderVertex = VertexDefinition.Get(mesh.Type); var streamTypes = renderVertex.GetStreamTypes(); foreach (var streamEntry in streamTypes) { var vertexBufferIndex = mesh.VertexBufferIndices[streamEntry.Key]; if (vertexBufferIndex == -1 || VertexBuffers.ContainsKey(vertexBufferIndex)) { continue; } var vbDef = RenderGeometryResource.VertexBuffers[vertexBufferIndex].Definition; var vb = new VertexBuffer(streamEntry.Value, vbDef.Data.Data.Length, device, Usage.DoNotClip, renderVertex.GetStreamFormat(streamEntry.Key), Pool.Managed); var vbData = vb.Lock(0, vbDef.Data.Data.Length, LockFlags.None); var vertices = Array.CreateInstance(streamEntry.Value, vbDef.Count); using (var vbDefData = new MemoryStream(vbDef.Data.Data)) using (var vbDefReader = new BinaryReader(vbDefData)) { for (var i = 0; i < vbDef.Count; i++) { var handle = GCHandle.Alloc(vbDefReader.ReadBytes(Marshal.SizeOf(streamEntry.Value)), GCHandleType.Pinned); var vertex = Marshal.PtrToStructure(handle.AddrOfPinnedObject(), streamEntry.Value); var positionField = streamEntry.Value.GetField("Position"); if (positionField != null) { var xyz = (Vector3)positionField.GetValue(vertex); positionField.SetValue(vertex, new Vector3( xyz.X * compression.X.Length + compression.X.Lower, xyz.Y * compression.Y.Length + compression.Y.Lower, xyz.Z * compression.Z.Length + compression.Z.Lower)); } var texcoordField = streamEntry.Value.GetField("Texcoord"); if (texcoordField != null) { var uv = (Vector2)texcoordField.GetValue(vertex); texcoordField.SetValue(vertex, new Vector2( uv.X * compression.U.Length + compression.U.Lower, uv.Y * compression.V.Length + compression.V.Lower)); } vertices.SetValue(vertex, i); handle.Free(); } } vbData.Write(vertices); vb.Unlock(); VertexBuffers[vertexBufferIndex] = vb; } foreach (var indexBufferIndex in mesh.IndexBufferIndices) { if (indexBufferIndex == -1 /*ushort.MaxValue*/ || IndexBuffers.ContainsKey(indexBufferIndex)) { continue; } var ibDef = RenderGeometryResource.IndexBuffers[indexBufferIndex].Definition; switch (ibDef.Format) { case IndexBufferFormat.PointList: mesh.IndexBufferType = TagPrimitiveType.PointList; break; case IndexBufferFormat.LineList: mesh.IndexBufferType = TagPrimitiveType.LineList; break; case IndexBufferFormat.LineStrip: mesh.IndexBufferType = TagPrimitiveType.LineStrip; break; case IndexBufferFormat.TriangleList: mesh.IndexBufferType = TagPrimitiveType.TriangleList; break; case IndexBufferFormat.TriangleFan: mesh.IndexBufferType = TagPrimitiveType.TriangleFan; break; case IndexBufferFormat.TriangleStrip: mesh.IndexBufferType = TagPrimitiveType.TriangleStrip; break; } var ib = new IndexBuffer(device, ibDef.Data.Data.Length, Usage.DoNotClip, Pool.Managed, true); var ibData = ib.Lock(0, ibDef.Data.Data.Length, LockFlags.None); /*resourceStream.Position = ibDef.Data.Address.Offset; * * var indices = new ushort[ibDef.Data.Data.Length / 2]; * * for (var i = 0; i < ibDef.Data.Data.Length / 2; i++) * indices[i] = reader.ReadUInt16();*/ // may not work, hard to test (original code above) short[] indices = new short[(int)Math.Ceiling(ibDef.Data.Data.Length / 2.0)]; Buffer.BlockCopy(ibDef.Data.Data, 0, indices, 0, ibDef.Data.Data.Length); ibData.Write(indices); ib.Unlock(); IndexBuffers[indexBufferIndex] = ib; } } } }
private List <ShaderTemplateItem> CollectRmt2Info(Stream cacheStream, CachedTag bmRmt2Instance, List <string> bmMaps, List <string> bmArgs) { var edRmt2BestStats = new List <ShaderTemplateItem>(); RenderMethodTemplate bmRmt2; PixelShader bmPixl; using (var blamStream = BlamCache.OpenCacheRead()) { bmRmt2 = BlamCache.Deserialize <RenderMethodTemplate>(blamStream, bmRmt2Instance); bmPixl = BlamCache.Deserialize <PixelShader>(blamStream, bmRmt2.PixelShader); } // loop trough all rmt2 and find the closest foreach (var edRmt2_ in Rmt2TagsInfo) { var rmt2Type = bmRmt2Instance.Name.Split("\\".ToArray())[1]; var edRmt2Tag = (CachedTagHaloOnline)CacheContext.TagCache.GetTag(edRmt2_.Key); // Ignore all rmt2 that are not of the same type. if (edRmt2Tag == null || !(edRmt2Tag.Name?.Contains(rmt2Type) ?? false)) { continue; } using (var reader = new EndianReader(cacheStream, true)) { reader.SeekTo(edRmt2Tag.HeaderOffset + edRmt2Tag.DefinitionOffset + 28); var edPixl = (CachedTagHaloOnline)CacheContext.TagCache.GetTag(reader.ReadInt32()); if (edPixl == null) { continue; } reader.SeekTo(edPixl.HeaderOffset + edPixl.DefinitionOffset + 0x4); var drawModeCount = reader.ReadInt32(); reader.SeekTo(edPixl.HeaderOffset + edPixl.DefinitionOffset + 0x14); var shaderCount = reader.ReadInt32(); if (bmPixl.DrawModes.Count > drawModeCount || bmPixl.Shaders.Count > shaderCount) { continue; } } int mapsCommon = 0; int argsCommon = 0; int mapsUncommon = 0; int argsUncommon = 0; int mapsMissing = 0; int argsMissing = 0; var edMaps_ = new List <string>(); var edArgs_ = new List <string>(); foreach (var a in edRmt2_.Value[0]) { edMaps_.Add(a); } foreach (var a in edRmt2_.Value[1]) { edArgs_.Add(a); } foreach (var a in bmMaps) { if (edMaps_.Contains(a)) { mapsCommon++; } } foreach (var a in bmMaps) { if (!edMaps_.Contains(a)) { mapsMissing++; } } foreach (var a in edMaps_) { if (!bmMaps.Contains(a)) { mapsUncommon++; } } foreach (var a in bmArgs) { if (edArgs_.Contains(a)) { argsCommon++; } } foreach (var a in bmArgs) { if (!edArgs_.Contains(a)) { argsMissing++; } } foreach (var a in edArgs_) { if (!bmArgs.Contains(a)) { argsUncommon++; } } edRmt2BestStats.Add(new ShaderTemplateItem { rmt2TagIndex = edRmt2_.Key, rmdfValuesMatchingCount = 0, mapsCountEd = edRmt2_.Value[0].Count, argsCountEd = edRmt2_.Value[1].Count, mapsCountBm = bmMaps.Count, argsCountBm = bmArgs.Count, mapsCommon = mapsCommon, argsCommon = argsCommon, mapsUncommon = mapsUncommon, argsUncommon = argsUncommon, mapsMissing = mapsMissing, argsMissing = argsMissing }); } return(edRmt2BestStats); }
public override object Execute(List <string> args) { var argStack = new Stack <string>(args.AsEnumerable().Reverse()); var portingFlags = ParsePortingFlags(argStack); if (argStack.Count < 1) { Console.WriteLine("ERROR: Expected bsp index!"); return(false); } var sbspIndex = int.Parse(argStack.Pop()); using (var blamCacheStream = BlamCache.OpenCacheRead()) using (var hoCacheStream = HoCache.OpenCacheReadWrite()) { var blamScnr = BlamCache.Deserialize <Scenario>(blamCacheStream, BlamCache.TagCache.FindFirstInGroup("scnr")); var blamSbsp = BlamCache.Deserialize <ScenarioStructureBsp>(blamCacheStream, blamScnr.StructureBsps[sbspIndex].StructureBsp); var desiredInstances = new Dictionary <int, string>(); if (argStack.Count > 0) { var identifier = argStack.Pop(); string desiredName = null; if (argStack.Count > 0) { desiredName = argStack.Pop(); } var index = FindBlockIndex(blamSbsp.InstancedGeometryInstances, identifier); desiredInstances.Add(index, desiredName); } else { Console.WriteLine("------------------------------------------------------------------"); Console.WriteLine("Enter each instance with the format <Name or Index> [New tagname]"); Console.WriteLine("Enter a blank line to finish."); Console.WriteLine("------------------------------------------------------------------"); for (string line; !String.IsNullOrWhiteSpace(line = Console.ReadLine());) { var parts = line.Split(' '); var identifier = parts[0]; var name = parts.Length > 1 ? string.Join(" ", parts.Skip(1)) : null; var index = FindBlockIndex(blamSbsp.InstancedGeometryInstances, identifier); if (index == -1) { Console.WriteLine($"ERROR: Instance not found by identifier {identifier}!"); return(false); } desiredInstances.Add(index, name); } } if (desiredInstances.Count < 1) { return(true); } var converter = new GeometryToObjectConverter(HoCache, hoCacheStream, BlamCache, blamCacheStream, blamScnr, sbspIndex); converter.PortTag.SetFlags(portingFlags); foreach (var kv in desiredInstances) { try { var instance = blamSbsp.InstancedGeometryInstances[kv.Key]; var tag = converter.ConvertGeometry(kv.Key, kv.Value); } finally { HoCache.SaveStrings(); HoCache.SaveTagNames(); } } } return(true); }