public bool ExportMeshWithMaterials(Stream meshStream, FileInfo outfile, List <Archive> archives, string matRepo, EUncookExtension eUncookExtension = EUncookExtension.dds, bool isGLBinary = true, bool LodFilter = true) { if (matRepo == null) { throw new Exception("Material Repository Path is not set, Please select a folder in the Material Repository Settings where your textures will output, Generating the complete dump is not required."); } var cr2w = _wolvenkitFileService.TryReadRED4File(meshStream); if (cr2w == null || !cr2w.Chunks.Select(_ => _.Data).OfType <CMesh>().Any() || !cr2w.Chunks.Select(_ => _.Data).OfType <rendRenderMeshBlob>().Any()) { return(false); } var rendblob = cr2w.Chunks.Select(_ => _.Data).OfType <rendRenderMeshBlob>().First(); var rendbuffer = cr2w.Buffers[rendblob.RenderBuffer.Buffer.Value - 1]; meshStream.Seek(rendbuffer.Offset, SeekOrigin.Begin); var ms = new MemoryStream(); meshStream.DecompressAndCopySegment(ms, rendbuffer.DiskSize, rendbuffer.MemSize); var meshesinfo = MeshTools.GetMeshesinfo(rendblob); List <RawMeshContainer> expMeshes = MeshTools.ContainRawMesh(ms, meshesinfo, LodFilter); MeshTools.UpdateSkinningParamCloth(ref expMeshes, meshStream, cr2w); RawArmature Rig = MeshTools.GetOrphanRig(rendblob); ModelRoot model = MeshTools.RawMeshesToGLTF(expMeshes, Rig); ParseMaterials(cr2w, meshStream, outfile, archives, matRepo, eUncookExtension); if (isGLBinary) { model.SaveGLB(outfile.FullName); } else { model.SaveGLTF(outfile.FullName); } meshStream.Dispose(); meshStream.Close(); return(true); }
public bool ExportMeshWithMaterials(Stream meshStream, FileInfo outfile, List <Archive> archives, string matRepo, EUncookExtension eUncookExtension = EUncookExtension.dds, bool isGLBinary = true, bool LodFilter = true) { if (matRepo == null) { throw new Exception("Material Repository Path is not set, Please select a folder in the Material Repository Settings where your textures will output, Generating the complete dump is not required."); } var cr2w = _wolvenkitFileService.ReadRed4File(meshStream); if (cr2w == null || cr2w.RootChunk is not CMesh cMesh || cMesh.RenderResourceBlob.Chunk is not rendRenderMeshBlob rendblob) { return(false); } using var ms = new MemoryStream(rendblob.RenderBuffer.Buffer.GetBytes()); var meshesinfo = MeshTools.GetMeshesinfo(rendblob, cr2w); var expMeshes = MeshTools.ContainRawMesh(ms, meshesinfo, LodFilter); MeshTools.UpdateSkinningParamCloth(ref expMeshes, meshStream, cr2w); var Rig = MeshTools.GetOrphanRig(rendblob, cr2w); var model = MeshTools.RawMeshesToGLTF(expMeshes, Rig); ParseMaterials(cr2w, meshStream, outfile, archives, matRepo, eUncookExtension); if (isGLBinary) { model.SaveGLB(outfile.FullName); } else { model.SaveGLTF(outfile.FullName); } meshStream.Dispose(); meshStream.Close(); return(true); }
public bool ExportMorphTargets(Stream targetStream, FileInfo outfile, List <Archive> archives, string modFolder, bool isGLBinary = true) { var cr2w = _wolvenkitFileService.ReadRed4File(targetStream); if (cr2w == null || cr2w.RootChunk is not MorphTargetMesh morphBlob || morphBlob.Blob.Chunk is not rendRenderMorphTargetMeshBlob blob || blob.BaseBlob.Chunk is not rendRenderMeshBlob rendblob) { return(false); } RawArmature Rig = null; { var hash = FNV1A64HashAlgorithm.HashString(morphBlob.BaseMesh.DepotPath); var meshStream = new MemoryStream(); foreach (var ar in archives) { if (ar.Files.ContainsKey(hash)) { ExtractSingleToStream(ar, hash, meshStream); break; } } var meshCr2w = _wolvenkitFileService.ReadRed4File(meshStream); if (meshCr2w != null && meshCr2w.RootChunk is MorphTargetMesh tBlob1 && tBlob1.Blob.Chunk is rendRenderMorphTargetMeshBlob tBlob2 && tBlob2.BaseBlob.Chunk is rendRenderMeshBlob tBlob3) { Rig = MeshTools.GetOrphanRig(tBlob3, meshCr2w); } } using var meshbuffer = new MemoryStream(rendblob.RenderBuffer.Buffer.GetBytes()); var meshesinfo = MeshTools.GetMeshesinfo(rendblob, cr2w); var expMeshes = MeshTools.ContainRawMesh(meshbuffer, meshesinfo, true); var diffsbuffer = new MemoryStream(); var mappingbuffer = new MemoryStream(); var texbuffer = new MemoryStream(); if (blob.DiffsBuffer is not null) { diffsbuffer = new MemoryStream(blob.DiffsBuffer.Buffer.GetBytes()); //targetStream.Seek(cr2w.Buffers[blob.DiffsBuffer.Buffer - 1].Offset, SeekOrigin.Begin); //targetStream.DecompressAndCopySegment(diffsbuffer, cr2w.Buffers[blob.DiffsBuffer.Buffer - 1].DiskSize, cr2w.Buffers[blob.DiffsBuffer.Buffer - 1].MemSize); } if (blob.MappingBuffer is not null) { mappingbuffer = new MemoryStream(blob.MappingBuffer.Buffer.GetBytes()); //targetStream.Seek(cr2w.Buffers[blob.MappingBuffer.Buffer - 1].Offset, SeekOrigin.Begin); //targetStream.DecompressAndCopySegment(mappingbuffer, cr2w.Buffers[blob.MappingBuffer.Buffer - 1].DiskSize, cr2w.Buffers[blob.MappingBuffer.Buffer - 1].MemSize); } if (blob.TextureDiffsBuffer is not null) { texbuffer = new MemoryStream(blob.TextureDiffsBuffer.Buffer.GetBytes()); //targetStream.Seek(cr2w.Buffers[blob.TextureDiffsBuffer.Buffer - 1].Offset, SeekOrigin.Begin); //targetStream.DecompressAndCopySegment(texbuffer, cr2w.Buffers[blob.TextureDiffsBuffer.Buffer - 1].DiskSize, cr2w.Buffers[blob.TextureDiffsBuffer.Buffer - 1].MemSize); } var targetsInfo = GetTargetInfos(cr2w, expMeshes.Count); var expTargets = new List <RawTargetContainer[]>(); for (var i = 0; i < targetsInfo.NumTargets; i++) { var temp_NumVertexDiffsInEachChunk = new uint[expMeshes.Count]; var temp_NumVertexDiffsMappingInEachChunk = new uint[expMeshes.Count]; for (var e = 0; e < expMeshes.Count; e++) { temp_NumVertexDiffsInEachChunk[e] = targetsInfo.NumVertexDiffsInEachChunk[i, e]; temp_NumVertexDiffsMappingInEachChunk[e] = targetsInfo.NumVertexDiffsMappingInEachChunk[i, e]; } expTargets.Add(ContainRawTargets(diffsbuffer, mappingbuffer, temp_NumVertexDiffsInEachChunk, temp_NumVertexDiffsMappingInEachChunk, targetsInfo.TargetStartsInVertexDiffs[i], targetsInfo.TargetStartsInVertexDiffsMapping[i], targetsInfo.TargetPositionDiffOffset[i], targetsInfo.TargetPositionDiffScale[i], expMeshes.Count)); } var textureStreams = ContainTextureStreams(blob, texbuffer); var model = RawTargetsToGLTF(expMeshes, expTargets, targetsInfo.Names, Rig); if (WolvenTesting.IsTesting) { return(true); } if (isGLBinary) { model.SaveGLB(outfile.FullName); } else { model.SaveGLTF(outfile.FullName); } var dir = new DirectoryInfo(outfile.FullName.Replace(Path.GetExtension(outfile.FullName), string.Empty) + "_Textures"); if (textureStreams.Count > 0) { Directory.CreateDirectory(dir.FullName); } for (var i = 0; i < textureStreams.Count; i++) { File.WriteAllBytes(dir.FullName + "\\" + Path.GetFileNameWithoutExtension(outfile.FullName) + i + ".dds", textureStreams[i].ToArray()); } targetStream.Dispose(); targetStream.Close(); return(true); }
public bool ImportMorphTargets(FileInfo inGltfFile, Stream intargetStream, List <Archive> archives, ValidationMode vmode = ValidationMode.Strict, Stream outStream = null) { var cr2w = _wolvenkitFileService.ReadRed4File(intargetStream); if (cr2w == null || cr2w.RootChunk is not MorphTargetMesh blob || blob.Blob.Chunk is not rendRenderMorphTargetMeshBlob renderblob || renderblob.BaseBlob.Chunk is not rendRenderMeshBlob rendblob) { return(false); } RawArmature newRig = null; { var hash = FNV1A64HashAlgorithm.HashString(blob.BaseMesh.DepotPath); var meshStream = new MemoryStream(); foreach (var ar in archives) { if (ar.Files.ContainsKey(hash)) { ExtractSingleToStream(ar, hash, meshStream); break; } } var meshCr2w = _wolvenkitFileService.ReadRed4File(meshStream); if (meshCr2w != null && meshCr2w.RootChunk is CMesh mesh && mesh.RenderResourceBlob.Chunk is rendRenderMeshBlob rendBlob) { newRig = MeshTools.GetOrphanRig(rendBlob, meshCr2w); } } var model = ModelRoot.Load(inGltfFile.FullName, new ReadSettings(vmode)); VerifyGLTF(model); var submeshCount = model.LogicalMeshes.Count; if (submeshCount == 0) { throw new Exception("No submeshes found in model file."); } using var diffsBuffer = new MemoryStream(); using var mappingsBuffer = new MemoryStream(); // Deserialize mappings buffer /*if (renderblob.MappingBuffer.IsSerialized) * { * intargetStream.Seek(cr2w.Buffers[mappingsBufferId].Offset, SeekOrigin.Begin); * intargetStream.DecompressAndCopySegment(mappingsBuffer, cr2w.Buffers[mappingsBufferId].DiskSize, cr2w.Buffers[mappingsBufferId].MemSize); * }*/ // Zero out some values that will be set later renderblob.Header.NumDiffs = 0; for (var i = 0; i < renderblob.Header.TargetStartsInVertexDiffs.Count; i++) { renderblob.Header.TargetStartsInVertexDiffs[i] = 0; } for (var i = 0; i < renderblob.Header.TargetStartsInVertexDiffsMapping.Count; i++) { renderblob.Header.TargetStartsInVertexDiffsMapping[i] = 0; } SetTargets(cr2w, model, renderblob, diffsBuffer, mappingsBuffer); renderblob.DiffsBuffer.Buffer.SetBytes(diffsBuffer.ToArray()); renderblob.MappingBuffer.Buffer.SetBytes(mappingsBuffer.ToArray()); VerifyGLTF(model); var Meshes = new List <RawMeshContainer>(); for (var i = 0; i < model.LogicalMeshes.Count; i++) { Meshes.Add(GltfMeshToRawContainer(model.LogicalMeshes[i])); } var max = new Vec3(Meshes[0].positions[0].X, Meshes[0].positions[0].Y, Meshes[0].positions[0].Z); var min = new Vec3(Meshes[0].positions[0].X, Meshes[0].positions[0].Y, Meshes[0].positions[0].Z); for (var e = 0; e < Meshes.Count; e++) { for (var i = 0; i < Meshes[e].positions.Length; i++) { if (Meshes[e].positions[i].X >= max.X) { max.X = Meshes[e].positions[i].X; } if (Meshes[e].positions[i].Y >= max.Y) { max.Y = Meshes[e].positions[i].Y; } if (Meshes[e].positions[i].Z >= max.Z) { max.Z = Meshes[e].positions[i].Z; } if (Meshes[e].positions[i].X <= min.X) { min.X = Meshes[e].positions[i].X; } if (Meshes[e].positions[i].Y <= min.Y) { min.Y = Meshes[e].positions[i].Y; } if (Meshes[e].positions[i].Z <= min.Z) { min.Z = Meshes[e].positions[i].Z; } } } // updating bounding box blob.BoundingBox.Min.X = min.X; blob.BoundingBox.Min.Y = min.Y; blob.BoundingBox.Min.Z = min.Z; blob.BoundingBox.Max.X = max.X; blob.BoundingBox.Max.Y = max.Y; blob.BoundingBox.Max.Z = max.Z; var QuantScale = new Vec4((max.X - min.X) / 2, (max.Y - min.Y) / 2, (max.Z - min.Z) / 2, 0); var QuantTrans = new Vec4((max.X + min.X) / 2, (max.Y + min.Y) / 2, (max.Z + min.Z) / 2, 1); RawArmature oldRig = null; if (model.LogicalSkins.Count != 0) { oldRig = new RawArmature { Names = new string[model.LogicalSkins[0].JointsCount] }; for (var i = 0; i < model.LogicalSkins[0].JointsCount; i++) { oldRig.Names[i] = model.LogicalSkins[0].GetJoint(i).Joint.Name; } } MeshTools.UpdateMeshJoints(ref Meshes, newRig, oldRig); var expMeshes = new List <Re4MeshContainer>(); for (var i = 0; i < Meshes.Count; i++) { expMeshes.Add(RawMeshToRE4Mesh(Meshes[i], QuantScale, QuantTrans)); } var meshBuffer = new MemoryStream(); var meshesInfo = BufferWriter(expMeshes, ref meshBuffer); meshesInfo.quantScale = QuantScale; meshesInfo.quantTrans = QuantTrans; var ms = GetEditedCr2wFile(cr2w, meshesInfo, meshBuffer); ms.Seek(0, SeekOrigin.Begin); if (outStream != null) { ms.CopyTo(outStream); } else { intargetStream.SetLength(0); ms.CopyTo(intargetStream); } return(true); }
public bool ExportMorphTargets(Stream targetStream, FileInfo outfile, List <Archive> archives, string modFolder, bool isGLBinary = true) { var cr2w = _wolvenkitFileService.TryReadRED4File(targetStream); if (cr2w == null || !cr2w.Chunks.Select(_ => _.Data).OfType <MorphTargetMesh>().Any() || !cr2w.Chunks.Select(_ => _.Data).OfType <rendRenderMeshBlob>().Any()) { return(false); } var morphBlob = cr2w.Chunks.Select(_ => _.Data).OfType <MorphTargetMesh>().First(); RawArmature Rig = null; { ulong hash = FNV1A64HashAlgorithm.HashString(morphBlob.BaseMesh.DepotPath); MemoryStream meshStream = new MemoryStream(); foreach (Archive ar in archives) { if (ar.Files.ContainsKey(hash)) { ExtractSingleToStream(ar, hash, meshStream); break; } } var meshCr2w = _wolvenkitFileService.TryReadRED4File(meshStream); if (meshCr2w != null && meshCr2w.Chunks.Select(_ => _.Data).OfType <CMesh>().Any() && meshCr2w.Chunks.Select(_ => _.Data).OfType <rendRenderMeshBlob>().Any()) { Rig = MeshTools.GetOrphanRig(meshCr2w.Chunks.Select(_ => _.Data).OfType <rendRenderMeshBlob>().First()); } } var rendblob = cr2w.Chunks.Select(_ => _.Data).OfType <rendRenderMeshBlob>().First(); var rendbuffer = cr2w.Buffers[rendblob.RenderBuffer.Buffer.Value - 1]; targetStream.Seek(rendbuffer.Offset, SeekOrigin.Begin); var meshbuffer = new MemoryStream(); targetStream.DecompressAndCopySegment(meshbuffer, rendbuffer.DiskSize, rendbuffer.MemSize); var meshesinfo = MeshTools.GetMeshesinfo(rendblob); List <RawMeshContainer> expMeshes = MeshTools.ContainRawMesh(meshbuffer, meshesinfo, true); var blob = cr2w.Chunks.Select(_ => _.Data).OfType <rendRenderMorphTargetMeshBlob>().First(); MemoryStream diffsbuffer = new MemoryStream(); MemoryStream mappingbuffer = new MemoryStream(); MemoryStream texbuffer = new MemoryStream(); if (blob.DiffsBuffer.IsSerialized) { targetStream.Seek(cr2w.Buffers[blob.DiffsBuffer.Buffer.Value - 1].Offset, SeekOrigin.Begin); targetStream.DecompressAndCopySegment(diffsbuffer, cr2w.Buffers[blob.DiffsBuffer.Buffer.Value - 1].DiskSize, cr2w.Buffers[blob.DiffsBuffer.Buffer.Value - 1].MemSize); } if (blob.MappingBuffer.IsSerialized) { targetStream.Seek(cr2w.Buffers[blob.MappingBuffer.Buffer.Value - 1].Offset, SeekOrigin.Begin); targetStream.DecompressAndCopySegment(mappingbuffer, cr2w.Buffers[blob.MappingBuffer.Buffer.Value - 1].DiskSize, cr2w.Buffers[blob.MappingBuffer.Buffer.Value - 1].MemSize); } if (blob.TextureDiffsBuffer.IsSerialized) { targetStream.Seek(cr2w.Buffers[blob.TextureDiffsBuffer.Buffer.Value - 1].Offset, SeekOrigin.Begin); targetStream.DecompressAndCopySegment(texbuffer, cr2w.Buffers[blob.TextureDiffsBuffer.Buffer.Value - 1].DiskSize, cr2w.Buffers[blob.TextureDiffsBuffer.Buffer.Value - 1].MemSize); } TargetsInfo targetsInfo = GetTargetInfos(cr2w, expMeshes.Count); List <RawTargetContainer[]> expTargets = new List <RawTargetContainer[]>(); for (int i = 0; i < targetsInfo.NumTargets; i++) { UInt32[] temp_NumVertexDiffsInEachChunk = new UInt32[expMeshes.Count]; UInt32[] temp_NumVertexDiffsMappingInEachChunk = new UInt32[expMeshes.Count]; for (int e = 0; e < expMeshes.Count; e++) { temp_NumVertexDiffsInEachChunk[e] = targetsInfo.NumVertexDiffsInEachChunk[i, e]; temp_NumVertexDiffsMappingInEachChunk[e] = targetsInfo.NumVertexDiffsMappingInEachChunk[i, e]; } expTargets.Add(ContainRawTargets(diffsbuffer, mappingbuffer, temp_NumVertexDiffsInEachChunk, temp_NumVertexDiffsMappingInEachChunk, targetsInfo.TargetStartsInVertexDiffs[i], targetsInfo.TargetStartsInVertexDiffsMapping[i], targetsInfo.TargetPositionDiffOffset[i], targetsInfo.TargetPositionDiffScale[i], expMeshes.Count)); } List <MemoryStream> textureStreams = ContainTextureStreams(blob, texbuffer); ModelRoot model = RawTargetsToGLTF(expMeshes, expTargets, targetsInfo.Names, Rig); if (WolvenTesting.IsTesting) { return(true); } if (isGLBinary) { model.SaveGLB(outfile.FullName); } else { model.SaveGLTF(outfile.FullName); } var dir = new DirectoryInfo(outfile.FullName.Replace(Path.GetExtension(outfile.FullName), string.Empty) + "_Textures"); if (textureStreams.Count > 0) { Directory.CreateDirectory(dir.FullName); } for (int i = 0; i < textureStreams.Count; i++) { File.WriteAllBytes(dir.FullName + "\\" + Path.GetFileNameWithoutExtension(outfile.FullName) + i + ".dds", textureStreams[i].ToArray()); } targetStream.Dispose(); targetStream.Close(); return(true); }