public override object Execute(List <string> args) { if (args.Count < 2) { return(false); } // // Verify Blam tag instance // var unitName = args[0].ToLower(); if (unitName != "spartan" && unitName != "elite") { Console.WriteLine("ERROR: Only 'spartan' and 'elite' armor variants are allowed."); return(false); } args.RemoveAt(0); var blamTagName = unitName == "spartan" ? @"objects\characters\masterchief\mp_masterchief\mp_masterchief" : @"objects\characters\elite\mp_elite\mp_elite"; Console.Write($"Verifying {blamTagName}.render_model..."); CacheFile.IndexItem blamTag = null; foreach (var tag in BlamCache.IndexItems) { if ((tag.GroupTag == "mode") && (tag.Name == blamTagName)) { blamTag = tag; break; } } if (blamTag == null) { Console.WriteLine($"ERROR: Blam tag does not exist: {blamTagName}.render_model"); return(true); } Console.WriteLine("done."); // // Load the Blam tag definition // var variantName = args[0]; args.RemoveAt(0); CachedTagInstance edModeTag = null; var isScenery = false; var regionNames = new List <string>(); while (args.Count != 0) { switch (args[0].ToLower()) { case "scenery": isScenery = true; args.RemoveAt(0); break; case "replace:": edModeTag = CacheContext.GetTag(args[1]); args.RemoveAt(1); args.RemoveAt(0); break; case "regions:": regionNames.AddRange(args.Skip(1)); args.Clear(); break; default: throw new InvalidDataException($"{args}"); } } var blamContext = new CacheSerializationContext(ref BlamCache, blamTag); var edModeDefinition = BlamCache.Deserializer.Deserialize <RenderModel>(blamContext); var materials = edModeDefinition.Materials.Select(i => new RenderMaterial { BreakableSurfaceIndex = i.BreakableSurfaceIndex, Properties = i.Properties, RenderMethod = i.RenderMethod, Skins = i.Skins, Unknown = i.Unknown, Unknown2 = i.Unknown2, Unknown3 = i.Unknown3, Unknown4 = i.Unknown4 }).ToList(); edModeDefinition = (RenderModel)ConvertData(null, edModeDefinition, false); var variantRegions = new List <RenderModel.Region>(); foreach (var region in edModeDefinition.Regions) { if (regionNames.Count != 0 && !regionNames.Contains(CacheContext.GetString(region.Name))) { continue; } var variantRegion = new RenderModel.Region { Name = region.Name, Permutations = new List <RenderModel.Region.Permutation>() }; foreach (var permutation in region.Permutations) { if (variantName == CacheContext.GetString(permutation.Name)) { variantRegion.Permutations.Add(permutation); } } variantRegions.Add(variantRegion); } var variantMeshes = new List <int>(); var variantMaterials = new List <int>(); var variantVertexBuffers = new List <int>(); var variantIndexBuffers = new List <int>(); foreach (var region in variantRegions) { foreach (var permutation in region.Permutations) { for (var i = permutation.MeshIndex; i < (short)(permutation.MeshIndex + permutation.MeshCount); i++) { var mesh = edModeDefinition.Geometry.Meshes[i]; foreach (var part in mesh.Parts) { if (part.MaterialIndex != -1 && !variantMaterials.Contains(part.MaterialIndex)) { variantMaterials.Add(part.MaterialIndex); } } foreach (var vertexBuffer in mesh.VertexBufferIndices) { if (vertexBuffer != ushort.MaxValue && !variantVertexBuffers.Contains(vertexBuffer)) { variantVertexBuffers.Add(vertexBuffer); } } foreach (var indexBuffer in mesh.IndexBufferIndices) { if (indexBuffer != ushort.MaxValue && !variantIndexBuffers.Contains(indexBuffer)) { variantIndexBuffers.Add(indexBuffer); } } if (!variantMeshes.Contains(i)) { variantMeshes.Add(i); } } } } variantMeshes.Sort(); variantMaterials.Sort(); variantVertexBuffers.Sort(); variantIndexBuffers.Sort(); foreach (var meshIndex in variantMeshes) { var mesh = edModeDefinition.Geometry.Meshes[meshIndex]; foreach (var part in mesh.Parts) { if (part.MaterialIndex != -1) { part.MaterialIndex = (short)variantMaterials.IndexOf(part.MaterialIndex); } } } foreach (var region in variantRegions) { foreach (var permutation in region.Permutations) { if (permutation.MeshIndex != -1) { permutation.MeshIndex = (short)variantMeshes.IndexOf(permutation.MeshIndex); } } } foreach (var meshIndex in variantMeshes) { var mesh = edModeDefinition.Geometry.Meshes[meshIndex]; for (var i = 0; i < mesh.VertexBufferIndices.Length; i++) { if (!variantVertexBuffers.Contains(mesh.VertexBufferIndices[i])) { mesh.VertexBufferIndices[i] = ushort.MaxValue; } else { mesh.VertexBufferIndices[i] = (ushort)variantVertexBuffers.IndexOf(mesh.VertexBufferIndices[i]); } } for (var i = 0; i < mesh.IndexBufferIndices.Length; i++) { if (!variantIndexBuffers.Contains(mesh.IndexBufferIndices[i])) { mesh.IndexBufferIndices[i] = ushort.MaxValue; } else { mesh.IndexBufferIndices[i] = (ushort)variantIndexBuffers.IndexOf(mesh.IndexBufferIndices[i]); } } } edModeDefinition.Regions = variantRegions; edModeDefinition.Geometry.Meshes = edModeDefinition.Geometry.Meshes.Where(i => variantMeshes.Contains(edModeDefinition.Geometry.Meshes.IndexOf(i))).ToList(); // // Port Blam render_model materials // materials = materials.Where(i => variantMaterials.Contains(materials.IndexOf(i))).ToList(); using (var stream = CacheContext.OpenTagCacheReadWrite()) { for (var i = 0; i < materials.Count; i++) { var material = materials[i]; if (material.RenderMethod.Index == -1) { continue; } var blamRenderMethod = materials[i].RenderMethod; var blamRenderMethodTag = BlamCache.IndexItems.GetItemByID(blamRenderMethod.Index); var renderMethodExists = false; foreach (var instance in CacheContext.TagCache.Index.FindAllInGroup("rm ")) { if (instance?.Name == blamRenderMethodTag.Name) { renderMethodExists = true; material.RenderMethod = instance; break; } } if (!renderMethodExists) { material.RenderMethod = CacheContext.GetTag <Shader>(@"shaders\invalid"); } } } edModeDefinition.Materials = materials; // // Load Blam resource data // var resourceData = BlamCache.GetRawFromID(edModeDefinition.Geometry.ZoneAssetHandle); if (resourceData == null) { Console.WriteLine("Blam render_geometry resource contains no data."); return(true); } // // Load Blam resource definition // Console.Write("Loading Blam render_geometry resource definition..."); var definitionEntry = BlamCache.ResourceGestalt.TagResources[edModeDefinition.Geometry.ZoneAssetHandle.Index]; var resourceDefinition = new RenderGeometryApiResourceDefinition { VertexBuffers = new List <TagStructureReference <VertexBufferDefinition> >(), IndexBuffers = new List <TagStructureReference <IndexBufferDefinition> >() }; using (var definitionStream = new MemoryStream(BlamCache.ResourceGestalt.FixupInformation)) using (var definitionReader = new EndianReader(definitionStream, EndianFormat.BigEndian)) { var dataContext = new DataSerializationContext(definitionReader, null, CacheResourceAddressType.Definition); definitionReader.SeekTo(definitionEntry.FixupInformationOffset + (definitionEntry.FixupInformationLength - 24)); var vertexBufferCount = definitionReader.ReadInt32(); definitionReader.Skip(8); var indexBufferCount = definitionReader.ReadInt32(); definitionReader.SeekTo(definitionEntry.FixupInformationOffset); for (var i = 0; i < vertexBufferCount; i++) { resourceDefinition.VertexBuffers.Add(new TagStructureReference <VertexBufferDefinition> { Definition = new VertexBufferDefinition { Count = definitionReader.ReadInt32(), Format = (VertexBufferFormat)definitionReader.ReadInt16(), VertexSize = definitionReader.ReadInt16(), Data = new TagData { Size = definitionReader.ReadInt32(), Unused4 = definitionReader.ReadInt32(), Unused8 = definitionReader.ReadInt32(), Address = new CacheResourceAddress(CacheResourceAddressType.Memory, definitionReader.ReadInt32()), Unused10 = definitionReader.ReadInt32() } } }); } definitionReader.Skip(vertexBufferCount * 12); for (var i = 0; i < indexBufferCount; i++) { resourceDefinition.IndexBuffers.Add(new TagStructureReference <IndexBufferDefinition> { Definition = new IndexBufferDefinition { Format = (IndexBufferFormat)definitionReader.ReadInt32(), Data = new TagData { Size = definitionReader.ReadInt32(), Unused4 = definitionReader.ReadInt32(), Unused8 = definitionReader.ReadInt32(), Address = new CacheResourceAddress(CacheResourceAddressType.Memory, definitionReader.ReadInt32()), Unused10 = definitionReader.ReadInt32() } } }); } } Console.WriteLine("done."); // // Convert Blam resource data // using (var edResourceStream = new MemoryStream()) { // // Convert Blam render_geometry_api_resource_definition // using (var blamResourceStream = new MemoryStream(resourceData)) { // // Convert Blam vertex buffers // Console.Write("Converting vertex buffers..."); var previousVertexBufferCount = -1; for (var i = 0; i < resourceDefinition.VertexBuffers.Count; i++) { if (!variantVertexBuffers.Contains(i)) { continue; } blamResourceStream.Position = definitionEntry.ResourceFixups[i].Offset; if (i > 0) { previousVertexBufferCount = resourceDefinition.VertexBuffers[i - 1].Definition.Count; } GeometryConverter.ConvertVertexBuffer(resourceDefinition, blamResourceStream, edResourceStream, i, previousVertexBufferCount); } Console.WriteLine("done."); // // Convert Blam index buffers // Console.Write("Converting index buffers..."); for (var i = 0; i < resourceDefinition.IndexBuffers.Count; i++) { if (!variantIndexBuffers.Contains(i)) { continue; } blamResourceStream.Position = definitionEntry.ResourceFixups[resourceDefinition.VertexBuffers.Count * 2 + i].Offset; GeometryConverter.ConvertIndexBuffer(resourceDefinition, blamResourceStream, edResourceStream, i); } Console.WriteLine("done."); } resourceDefinition.VertexBuffers = resourceDefinition.VertexBuffers.Where(i => variantVertexBuffers.Contains(resourceDefinition.VertexBuffers.IndexOf(i))).ToList(); resourceDefinition.IndexBuffers = resourceDefinition.IndexBuffers.Where(i => variantIndexBuffers.Contains(resourceDefinition.IndexBuffers.IndexOf(i))).ToList(); // // Finalize the new ElDorado geometry resource // Console.Write("Writing resource data..."); edModeDefinition.Geometry.Resource = new PageableResource { Page = new RawPage(), Resource = new TagResourceGen3 { ResourceType = TagResourceTypeGen3.RenderGeometry, ResourceFixups = new List <TagResourceGen3.ResourceFixup>(), ResourceDefinitionFixups = new List <TagResourceGen3.ResourceDefinitionFixup>(), Unknown2 = 1 } }; edResourceStream.Position = 0; var resourceContext = new ResourceSerializationContext(CacheContext, edModeDefinition.Geometry.Resource); CacheContext.Serializer.Serialize(resourceContext, resourceDefinition); edModeDefinition.Geometry.Resource.ChangeLocation(ResourceLocation.ResourcesB); CacheContext.AddResource(edModeDefinition.Geometry.Resource, edResourceStream); Console.WriteLine("done."); } edModeDefinition.Name = CacheContext.GetStringId(variantName); if (edModeTag == null) { for (var i = 0; i < CacheContext.TagCache.Index.Count; i++) { if (CacheContext.TagCache.Index[i] == null) { CacheContext.TagCache.Index[i] = edModeTag = new CachedTagInstance(i, TagGroup.Instances[new Tag("mode")]); break; } } if (edModeTag == null) { edModeTag = CacheContext.TagCache.AllocateTag(TagGroup.Instances[new Tag("mode")]); } } // // Create a new armor model tag // Model edHlmtDefinition = null; CachedTagInstance edHlmtTag = null; if (isScenery) { Console.Write($"Verifying {blamTagName}.model..."); CacheFile.IndexItem blamHlmtTag = null; foreach (var tag in BlamCache.IndexItems) { if ((tag.GroupTag == "hlmt") && (tag.Name == blamTagName)) { blamHlmtTag = tag; break; } } if (blamHlmtTag == null) { Console.WriteLine($"ERROR: Blam tag does not exist: {blamTagName}.model"); return(true); } Console.WriteLine("done."); blamContext = new CacheSerializationContext(ref BlamCache, blamHlmtTag); edHlmtDefinition = (Model)ConvertData(null, BlamCache.Deserializer.Deserialize <Model>(blamContext), false); edHlmtDefinition.RenderModel = edModeTag; edHlmtDefinition.ReduceToL1SuperLow = 36.38004f; edHlmtDefinition.ReduceToL2Low = 27.28503f; edHlmtDefinition.Variants = new List <Model.Variant>(); edHlmtDefinition.Materials = new List <Model.Material>(); edHlmtDefinition.NewDamageInfo = new List <Model.GlobalDamageInfoBlock>(); edHlmtDefinition.Targets = new List <Model.Target>(); var collisionRegions = new List <Model.CollisionRegion>(); foreach (var collisionRegion in edHlmtDefinition.CollisionRegions) { var found = false; foreach (var variantRegion in variantRegions) { if (collisionRegion.Name == variantRegion.Name) { found = true; break; } } if (!found) { continue; } found = false; foreach (var permutation in collisionRegion.Permutations) { if (permutation.Name == CacheContext.GetStringId(variantName)) { found = true; break; } } if (found) { collisionRegions.Add(collisionRegion); } } foreach (var collisionRegion in collisionRegions) { Model.CollisionRegion.Permutation permutation = null; foreach (var collisionPermutation in collisionRegion.Permutations) { if (collisionPermutation.Name == CacheContext.GetStringId(variantName)) { permutation = collisionPermutation; break; } } if (permutation == null) { throw new KeyNotFoundException(); } collisionRegion.Permutations = new List <Model.CollisionRegion.Permutation> { permutation }; } edHlmtDefinition.CollisionRegions = collisionRegions; for (var i = 0; i < CacheContext.TagCache.Index.Count; i++) { if (CacheContext.TagCache.Index[i] == null) { CacheContext.TagCache.Index[i] = edHlmtTag = new CachedTagInstance(i, TagGroup.Instances[new Tag("hlmt")]); break; } } if (edHlmtTag == null) { edHlmtTag = CacheContext.TagCache.AllocateTag(TagGroup.Instances[new Tag("hlmt")]); } } // // Create a new armor scenery tag // Scenery edScenDefinition = null; CachedTagInstance edScenTag = null; if (isScenery) { edScenDefinition = new Scenery { ObjectType = new GameObjectType { Halo2 = GameObjectTypeHalo2.Scenery, Halo3Retail = GameObjectTypeHalo3Retail.Scenery, Halo3ODST = GameObjectTypeHalo3ODST.Scenery, HaloOnline = GameObjectTypeHaloOnline.Scenery }, BoundingRadius = 0.44f, BoundingOffset = new RealPoint3d(-0.02f, 0.0f, 0.0f), AccelerationScale = 1.2f, SweetenerSize = GameObject.SweetenerSizeValue.Medium, Model = edHlmtTag, ChangeColors = new List <GameObject.ChangeColor> { new GameObject.ChangeColor(), new GameObject.ChangeColor(), new GameObject.ChangeColor(), new GameObject.ChangeColor(), new GameObject.ChangeColor() }, NodeMaps = new List <GameObject.NodeMap>() }; for (sbyte i = 0; i < 51; i++) { edScenDefinition.NodeMaps.Add(new GameObject.NodeMap { TargetNode = i }); } for (var i = 0; i < CacheContext.TagCache.Index.Count; i++) { if (CacheContext.TagCache.Index[i] == null) { CacheContext.TagCache.Index[i] = edScenTag = new CachedTagInstance(i, TagGroup.Instances[new Tag("scen")]); break; } } if (edScenTag == null) { edScenTag = CacheContext.TagCache.AllocateTag(TagGroup.Instances[new Tag("scen")]); } } // // Serialize new ElDorado tag definitions // using (var cacheStream = CacheContext.OpenTagCacheReadWrite()) { CacheContext.Serialize(cacheStream, edModeTag, edModeDefinition); edModeTag.Name = isScenery ? (unitName == "spartan" ? $@"objects\characters\masterchief\mp_masterchief\armor\{variantName}" : $@"objects\characters\elite\mp_elite\armor\{variantName}") : (unitName == "spartan" ? @"objects\characters\masterchief\mp_masterchief\mp_masterchief" : @"objects\characters\elite\mp_elite\mp_elite"); if (isScenery) { CacheContext.Serialize(cacheStream, edHlmtTag, edHlmtDefinition); CacheContext.Serialize(cacheStream, edScenTag, edScenDefinition); edScenTag.Name = unitName == "spartan" ? $@"objects\characters\masterchief\mp_masterchief\armor\{variantName}" : $@"objects\characters\elite\mp_elite\armor\{variantName}"; } } return(true); }
public override object Execute(List <string> args) { if (args.Count != 0) { return(false); } var soundDataAggregate = new byte[0].AsEnumerable(); int currentFileOffset = 0; int totalSampleCount = 0; int maxPermutationSampleCount = 0; int pitchRangeCount = GetPitchRangeCountUser(); if (pitchRangeCount <= 0) { return(false); } // // Get basic information on the sounds // if (pitchRangeCount > 1) { Definition.ImportType = ImportType.MultiLayer; } else { Definition.ImportType = ImportType.SingleLayer; } Definition.SampleRate.value = GetSoundSampleRateUser(); Definition.PlatformCodec.Compression = GetSoundCompressionUser(); Definition.PlatformCodec.Encoding = GetSoundEncodingUser(); Definition.PitchRanges = new List <PitchRange>(); // // For each pitch range, get all the permutations and append sound data. // for (int u = 0; u < pitchRangeCount; u++) { int permutationCount = GetPermutationCountUser(); if (permutationCount <= 0) { return(false); } var pitchRange = new PitchRange { ImportName = new StringId(5221), //|default| Unknown5 = -1, Unknown6 = -1, Unknown7 = -1, Unknown8 = -1, PermutationCount = (short)permutationCount, PitchRangeParameters = new PitchRangeParameter() }; pitchRange.PitchRangeParameters.UnknownBounds = new Bounds <short>(-32768, 32767); pitchRange.Permutations = new List <Permutation>(); // // Permutation section // for (int i = 0; i < permutationCount; i++) { string soundFile = GetPermutationFileUser(i); if (soundFile == null) { return(false); } int sampleCount = GetPermutationSampleCountUser(i); var perm = new Permutation { ImportName = StringId.Invalid, SampleSize = (uint)sampleCount }; if (i != 0) { perm.IsNotFirstPermutation = 1; } perm.PermutationNumber = (uint)i; var permutationData = File.ReadAllBytes(soundFile); perm.PermutationChunks = new List <PermutationChunk>(); var chunk = new PermutationChunk(currentFileOffset, permutationData.Length); perm.PermutationChunks.Add(chunk); currentFileOffset += permutationData.Length; totalSampleCount += sampleCount; if (maxPermutationSampleCount < sampleCount) { maxPermutationSampleCount = sampleCount; } soundDataAggregate = soundDataAggregate.Concat(permutationData); pitchRange.Permutations.Add(perm); } Definition.PitchRanges.Add(pitchRange); } Definition.Promotion.LongestPermutationDuration = (uint)(1000 * (double)maxPermutationSampleCount / (Definition.SampleRate.GetSampleRateHz())); Definition.Promotion.TotalSampleSize = (uint)totalSampleCount; // remove extra info for now Definition.ExtraInfo = new List <ExtraInfo>(); // // Create new resource // Console.Write("Creating new sound resource..."); var data = soundDataAggregate.ToArray(); Definition.Unknown12 = 0; using (var dataStream = new MemoryStream(data)) { var fileSize = (int)dataStream.Length; var resourceContext = new ResourceSerializationContext(CacheContext, Definition.Resource); CacheContext.Serializer.Serialize(resourceContext, new SoundResourceDefinition { Data = new TagData(fileSize, new CacheResourceAddress(CacheResourceAddressType.Resource, 0)) }); Definition.Resource = new PageableResource { Page = new RawPage { Index = -1 }, Resource = new TagResourceGen3 { ResourceType = TagResourceTypeGen3.Sound, DefinitionData = new byte[20], DefinitionAddress = new CacheResourceAddress(CacheResourceAddressType.Definition, 536870912), ResourceFixups = new List <TagResourceGen3.ResourceFixup> { new TagResourceGen3.ResourceFixup { BlockOffset = 12, Address = new CacheResourceAddress(CacheResourceAddressType.Resource, 1073741824) } }, ResourceDefinitionFixups = new List <TagResourceGen3.ResourceDefinitionFixup>(), Unknown2 = 1 } }; Definition.Resource.ChangeLocation(ResourceLocation.ResourcesB); CacheContext.AddResource(Definition.Resource, dataStream); for (int i = 0; i < 4; i++) { Definition.Resource.Resource.DefinitionData[i] = (byte)(Definition.Resource.Page.UncompressedBlockSize >> (i * 8)); } Console.WriteLine("done."); } return(true); }
public override object Execute(List <string> args) { if (args.Count != 1) { return(false); } if (!CacheContext.TryGetTag <Shader>(@"shaders\invalid", out var defaultShaderTag)) { Console.WriteLine("WARNING: 'shaders\\invalid.shader' not found!"); Console.WriteLine("You will have to assign material shaders manually."); } var stringIdCount = CacheContext.StringIdCache.Strings.Count; var sceneFile = new FileInfo(args[0]); if (!sceneFile.Exists) { throw new FileNotFoundException(sceneFile.FullName); } if (sceneFile.Extension.ToLower() != ".dae") { throw new FormatException($"Input file is not COLLADA format: {sceneFile.FullName}"); } Scene scene; using (var importer = new AssimpContext()) { scene = importer.ImportFile(sceneFile.FullName, PostProcessSteps.CalculateTangentSpace | PostProcessSteps.GenerateNormals | PostProcessSteps.SortByPrimitiveType | PostProcessSteps.Triangulate); } var builder = new RenderModelBuilder(CacheContext); var nodes = new Dictionary <string, sbyte>(); var materialIndices = new Dictionary <string, short>(); foreach (var oldNode in Definition.Nodes) { var name = CacheContext.GetString(oldNode.Name); nodes[name] = builder.AddNode(oldNode); } foreach (var region in Definition.Regions) { builder.BeginRegion(region.Name); var regionName = CacheContext.GetString(region.Name); foreach (var permutation in region.Permutations) { if (permutation.MeshCount > 1) { throw new NotSupportedException("multiple permutation meshes"); } if (permutation.MeshIndex == -1) { continue; } var permName = CacheContext.GetString(permutation.Name); var meshName = $"{regionName}FBXASC058{permName}Mesh"; var permMeshes = scene.Meshes.Where(i => i.Name == meshName).ToList(); if (permMeshes.Count == 0) { throw new Exception($"No mesh(es) found for region '{regionName}' permutation '{permName}'!"); } permMeshes.Sort((a, b) => a.MaterialIndex.CompareTo(b.MaterialIndex)); // Build a multipart mesh from the model data, // with each model mesh mapping to a part of one large mesh and having its own material ushort partStartVertex = 0; ushort partStartIndex = 0; var rigidVertices = new List <RigidVertex>(); var skinnedVertices = new List <SkinnedVertex>(); var indices = new List <ushort>(); var vertexType = Definition.Geometry.Meshes[permutation.MeshIndex].Type; var rigidNode = Definition.Geometry.Meshes[permutation.MeshIndex].RigidNodeIndex; builder.BeginPermutation(permutation.Name); builder.BeginMesh(); foreach (var mesh in permMeshes) { for (var i = 0; i < mesh.VertexCount; i++) { var position = mesh.Vertices[i]; var normal = mesh.Normals[i]; Vector3D uv; try { uv = mesh.TextureCoordinateChannels[0][i]; } catch { Console.WriteLine($"WARNING: Missing texture coordinate for vertex {i} in '{regionName}:{permName}'"); uv = new Vector3D(); } var tangent = mesh.Tangents.Count != 0 ? mesh.Tangents[i] : new Vector3D(); var bitangent = mesh.BiTangents.Count != 0 ? mesh.BiTangents[i] : new Vector3D(); if (vertexType == VertexType.Skinned) { var blendIndicesList = new List <byte>(); var blendWeightsList = new List <float>(); foreach (var bone in mesh.Bones) { foreach (var vertexInfo in bone.VertexWeights) { if (vertexInfo.VertexID == i) { // HAX BELOW //if (bone.Name.StartsWith("_")) //bone.Name = bone.Name.Substring(4); //if (bone.Name.EndsWith("2")) //bone.Name = bone.Name.Replace("2", "_tip"); //else if (bone.Name != "spine1" && bone.Name.EndsWith("1")) //bone.Name = bone.Name.Replace("1", "_low"); blendIndicesList.Add((byte)nodes[bone.Name]); blendWeightsList.Add(vertexInfo.Weight); } } } var blendIndices = new byte[4]; var blendWeights = new float[4]; for (int j = 0; j < blendIndicesList.Count; j++) { if (j < 4) { blendIndices[j] = blendIndicesList[j]; } } for (int j = 0; j < blendWeightsList.Count; j++) { if (j < 4) { blendWeights[j] = blendWeightsList[j]; } } skinnedVertices.Add(new SkinnedVertex { Position = new RealQuaternion(position.X * 0.01f, position.Y * 0.01f, position.Z * 0.01f, 1), Texcoord = new RealVector2d(uv.X, -uv.Y), Normal = new RealVector3d(normal.X, normal.Y, normal.Z), Tangent = new RealQuaternion(tangent.X, tangent.Y, tangent.Z, 1), Binormal = new RealVector3d(bitangent.X, bitangent.Y, bitangent.Z), BlendIndices = blendIndices, BlendWeights = blendWeights }); } else { rigidVertices.Add(new RigidVertex { Position = new RealQuaternion(position.X * 0.01f, position.Y * 0.01f, position.Z * 0.01f, 1), Texcoord = new RealVector2d(uv.X, -uv.Y), Normal = new RealVector3d(normal.X, normal.Y, normal.Z), Tangent = new RealQuaternion(tangent.X, tangent.Y, tangent.Z, 1), Binormal = new RealVector3d(bitangent.X, bitangent.Y, bitangent.Z), }); } } // Build the index buffer var meshIndices = mesh.GetIndices(); indices.AddRange(meshIndices.Select(i => (ushort)(i + partStartVertex))); // Define a material and part for this mesh var meshMaterial = scene.Materials[mesh.MaterialIndex]; short materialIndex = 0; if (materialIndices.ContainsKey(meshMaterial.Name)) { materialIndex = materialIndices[meshMaterial.Name]; } else { materialIndex = materialIndices[meshMaterial.Name] = builder.AddMaterial(new RenderMaterial { RenderMethod = defaultShaderTag, }); } builder.BeginPart(materialIndex, partStartIndex, (ushort)meshIndices.Length, (ushort)mesh.VertexCount); builder.DefineSubPart(partStartIndex, (ushort)meshIndices.Length, (ushort)mesh.VertexCount); builder.EndPart(); // Move to the next part partStartVertex += (ushort)mesh.VertexCount; partStartIndex += (ushort)meshIndices.Length; } // Bind the vertex and index buffers if (vertexType == VertexType.Skinned) { builder.BindSkinnedVertexBuffer(skinnedVertices); } else { builder.BindRigidVertexBuffer(rigidVertices, rigidNode); } builder.BindIndexBuffer(indices, IndexBufferFormat.TriangleList); builder.EndMesh(); builder.EndPermutation(); } builder.EndRegion(); } using (var resourceStream = new MemoryStream()) { Console.Write("Building render_geometry..."); var newDefinition = builder.Build(CacheContext.Serializer, resourceStream); Definition.Regions = newDefinition.Regions; Definition.Geometry = newDefinition.Geometry; Definition.Nodes = newDefinition.Nodes; Definition.Materials = newDefinition.Materials; resourceStream.Position = 0; Definition.Geometry.Resource.ChangeLocation(ResourceLocation.ResourcesB); CacheContext.AddResource(Definition.Geometry.Resource, resourceStream); Console.WriteLine("done."); } // // TODO: Build the new render_model and update the original render_model here... // Console.Write("Writing render_model tag data..."); using (var cacheStream = CacheContext.OpenTagCacheReadWrite()) CacheContext.Serialize(cacheStream, Tag, Definition); Console.WriteLine("done."); if (stringIdCount != CacheContext.StringIdCache.Strings.Count) { Console.Write("Saving string ids..."); using (var stream = CacheContext.OpenStringIdCacheReadWrite()) CacheContext.StringIdCache.Save(stream); Console.WriteLine("done"); } Console.WriteLine("Replaced render_geometry successfully."); return(true); }
public override object Execute(List <string> args) { if (args.Count != 1) { return(false); } var resourceFile = new FileInfo(args[0]); var fileSize = 0; if (!resourceFile.Exists) { Console.WriteLine($"ERROR: File not found: \"{resourceFile.FullName}\""); return(true); } // // Create new resource // Console.Write("Creating new sound resource..."); Definition.Unknown12 = 0; using (var dataStream = resourceFile.OpenRead()) { fileSize = (int)dataStream.Length; var resourceContext = new ResourceSerializationContext(CacheContext, Definition.Resource); CacheContext.Serializer.Serialize(resourceContext, new SoundResourceDefinition { Data = new TagData(fileSize, new CacheAddress(CacheAddressType.Resource, 0)) }); Definition.Resource = new PageableResource { Page = new RawPage { Index = -1 }, Resource = new TagResourceGen3 { ResourceType = TagResourceTypeGen3.Sound, DefinitionData = new byte[20], DefinitionAddress = new CacheAddress(CacheAddressType.Definition, 536870912), ResourceFixups = new List <TagResourceGen3.ResourceFixup> { new TagResourceGen3.ResourceFixup { BlockOffset = 12, Address = new CacheAddress(CacheAddressType.Resource, 1073741824) } }, ResourceDefinitionFixups = new List <TagResourceGen3.ResourceDefinitionFixup>(), Unknown2 = 1 } }; Definition.Resource.ChangeLocation(ResourceLocation.ResourcesB); CacheContext.AddResource(Definition.Resource, dataStream); for (int i = 0; i < 4; i++) { Definition.Resource.Resource.DefinitionData[i] = (byte)(Definition.Resource.Page.UncompressedBlockSize >> (i * 8)); } Console.WriteLine("done."); } // // Adjust tag definition to use correctly the sound file. // var chunkSize = (ushort)fileSize; var permutationChunk = new PermutationChunk(0, chunkSize); var permutation = Definition.PitchRanges[0].Permutations[0]; permutation.PermutationChunks = new List <PermutationChunk> { permutationChunk }; permutation.PermutationNumber = 0; permutation.SampleSize = 0; permutation.IsNotFirstPermutation = 0; Definition.PitchRanges[0].Permutations = new List <Permutation> { permutation }; Definition.PlatformCodec.Compression = Compression.MP3; return(true); }