public bool ExportMeshWithRig(Stream meshStream, Stream rigStream, FileInfo outfile, bool LodFilter = true, bool isGLBinary = true) { RawArmature Rig = _rig.ProcessRig(rigStream); var cr2w = _wolvenkitFileService.TryReadRED4File(meshStream); if (cr2w == null || !cr2w.Chunks.Select(_ => _.Data).OfType <CMesh>().Any()) { return(false); } if (!cr2w.Chunks.Select(_ => _.Data).OfType <rendRenderMeshBlob>().Any()) { return(false); } MemoryStream ms = GetMeshBufferStream(meshStream, cr2w); MeshesInfo meshinfo = GetMeshesinfo(cr2w); MeshBones bones = new MeshBones(); CMesh cmesh = cr2w.Chunks.Select(_ => _.Data).OfType <CMesh>().First(); if (cmesh.BoneNames.Count != 0) // for rigid meshes { bones.Names = RIG.GetboneNames(cr2w); bones.WorldPosn = GetMeshBonesPosn(cr2w); } List <RawMeshContainer> expMeshes = ContainRawMesh(ms, meshinfo, LodFilter); if (cmesh.BoneNames.Count == 0) // for rigid meshes { for (int i = 0; i < expMeshes.Count; i++) { expMeshes[i].weightcount = 0; } } UpdateMeshJoints(ref expMeshes, Rig, bones); ModelRoot model = RawMeshesToGLTF(expMeshes, Rig); if (isGLBinary) { model.SaveGLB(outfile.FullName); } else { model.SaveGLTF(outfile.FullName); } meshStream.Dispose(); meshStream.Close(); rigStream.Dispose(); rigStream.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.TryReadRED4File(meshStream); if (cr2w == null || !cr2w.Chunks.Select(_ => _.Data).OfType <CMesh>().Any() || !cr2w.Chunks.Select(_ => _.Data).OfType <rendRenderMeshBlob>().Any()) { return(false); } MeshTools.MeshBones meshBones = new MeshTools.MeshBones(); meshBones.boneCount = cr2w.Chunks.Select(_ => _.Data).OfType <CMesh>().First().BoneNames.Count; if (meshBones.boneCount != 0) // for rigid meshes { meshBones.Names = RIG.GetboneNames(cr2w); meshBones.WorldPosn = MeshTools.GetMeshBonesPosn(cr2w); } RawArmature Rig = MeshTools.GetNonParentedRig(meshBones); MemoryStream ms = MeshTools.GetMeshBufferStream(meshStream, cr2w); MeshesInfo meshinfo = MeshTools.GetMeshesinfo(cr2w); List <RawMeshContainer> expMeshes = MeshTools.ContainRawMesh(ms, meshinfo, LodFilter); if (meshBones.boneCount == 0) // for rigid meshes { for (int i = 0; i < expMeshes.Count; i++) { expMeshes[i].weightcount = 0; } } MeshTools.UpdateMeshJoints(ref expMeshes, Rig, meshBones); 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); }
private static ModelRoot RawTargetsToGLTF(List <RawMeshContainer> meshes, List <RawTargetContainer[]> expTargets, string[] names, RawArmature rig) { var model = ModelRoot.CreateModel(); var mat = model.CreateMaterial("Default"); mat.WithPBRMetallicRoughness().WithDefault(); mat.DoubleSided = true; var skins = new List <Skin>(); if (rig != null) { var skin = model.CreateSkin(); skin.BindJoints(RIG.ExportNodes(ref model, rig).Values.ToArray()); skins.Add(skin); } var ms = new MemoryStream(); var bw = new BinaryWriter(ms); var mIndex = -1; foreach (var mesh in meshes) { ++mIndex; for (var i = 0; i < mesh.positions.Length; i++) { bw.Write(mesh.positions[i].X); bw.Write(mesh.positions[i].Y); bw.Write(mesh.positions[i].Z); } for (var i = 0; i < mesh.normals.Length; i++) { bw.Write(mesh.normals[i].X); bw.Write(mesh.normals[i].Y); bw.Write(mesh.normals[i].Z); } for (var i = 0; i < mesh.tangents.Length; i++) { bw.Write(mesh.tangents[i].X); bw.Write(mesh.tangents[i].Y); bw.Write(mesh.tangents[i].Z); bw.Write(mesh.tangents[i].W); } for (var i = 0; i < mesh.colors0.Length; i++) { bw.Write(mesh.colors0[i].X); bw.Write(mesh.colors0[i].Y); bw.Write(mesh.colors0[i].Z); bw.Write(mesh.colors0[i].W); } for (var i = 0; i < mesh.colors1.Length; i++) { bw.Write(mesh.colors1[i].X); bw.Write(mesh.colors1[i].Y); bw.Write(mesh.colors1[i].Z); bw.Write(mesh.colors1[i].W); } for (var i = 0; i < mesh.texCoords0.Length; i++) { bw.Write(mesh.texCoords0[i].X); bw.Write(mesh.texCoords0[i].Y); } for (var i = 0; i < mesh.texCoords1.Length; i++) { bw.Write(mesh.texCoords1[i].X); bw.Write(mesh.texCoords1[i].Y); } if (mesh.weightCount > 0) { if (rig != null) { for (var i = 0; i < mesh.positions.Length; i++) { bw.Write(mesh.boneindices[i, 0]); bw.Write(mesh.boneindices[i, 1]); bw.Write(mesh.boneindices[i, 2]); bw.Write(mesh.boneindices[i, 3]); } for (var i = 0; i < mesh.positions.Length; i++) { bw.Write(mesh.weights[i, 0]); bw.Write(mesh.weights[i, 1]); bw.Write(mesh.weights[i, 2]); bw.Write(mesh.weights[i, 3]); } if (mesh.weightCount > 4) { for (var i = 0; i < mesh.positions.Length; i++) { bw.Write(mesh.boneindices[i, 4]); bw.Write(mesh.boneindices[i, 5]); bw.Write(mesh.boneindices[i, 6]); bw.Write(mesh.boneindices[i, 7]); } for (var i = 0; i < mesh.positions.Length; i++) { bw.Write(mesh.weights[i, 4]); bw.Write(mesh.weights[i, 5]); bw.Write(mesh.weights[i, 6]); bw.Write(mesh.weights[i, 7]); } } } } for (var i = 0; i < mesh.indices.Length; i += 3) { bw.Write(Convert.ToUInt16(mesh.indices[i + 1])); bw.Write(Convert.ToUInt16(mesh.indices[i + 0])); bw.Write(Convert.ToUInt16(mesh.indices[i + 2])); } for (var i = 0; i < expTargets.Count; i++) { var mappings = expTargets[i][mIndex].vertexMapping.ToList(); for (ushort e = 0; e < mesh.positions.Length; e++) { if (mappings.Contains(e)) { var idx = mappings.IndexOf(e); bw.Write(expTargets[i][mIndex].vertexDelta[idx].X); bw.Write(expTargets[i][mIndex].vertexDelta[idx].Y); bw.Write(expTargets[i][mIndex].vertexDelta[idx].Z); } else { bw.Write(0f); bw.Write(0f); bw.Write(0f); } } for (ushort e = 0; e < mesh.normals.Length; e++) { if (mappings.Contains(e)) { var idx = mappings.IndexOf(e); bw.Write(expTargets[i][mIndex].normalDelta[idx].X); bw.Write(expTargets[i][mIndex].normalDelta[idx].Y); bw.Write(expTargets[i][mIndex].normalDelta[idx].Z); } else { bw.Write(0f); bw.Write(0f); bw.Write(0f); } } for (ushort e = 0; e < mesh.tangents.Length; e++) { if (mappings.Contains(e)) { var idx = mappings.IndexOf(e); bw.Write(expTargets[i][mIndex].tangentDelta[idx].X); bw.Write(expTargets[i][mIndex].tangentDelta[idx].Y); bw.Write(expTargets[i][mIndex].tangentDelta[idx].Z); } else { bw.Write(0f); bw.Write(0f); bw.Write(0f); } } } } var buffer = model.UseBuffer(ms.ToArray()); var BuffViewoffset = 0; foreach (var mesh in meshes) { var mes = model.CreateMesh(mesh.name); var prim = mes.CreatePrimitive(); prim.Material = mat; { var acc = model.CreateAccessor(); var buff = model.UseBufferView(buffer, BuffViewoffset, mesh.positions.Length * 12); acc.SetData(buff, 0, mesh.positions.Length, DimensionType.VEC3, EncodingType.FLOAT, false); prim.SetVertexAccessor("POSITION", acc); BuffViewoffset += mesh.positions.Length * 12; } if (mesh.normals.Length > 0) { var acc = model.CreateAccessor(); var buff = model.UseBufferView(buffer, BuffViewoffset, mesh.normals.Length * 12); acc.SetData(buff, 0, mesh.normals.Length, DimensionType.VEC3, EncodingType.FLOAT, false); prim.SetVertexAccessor("NORMAL", acc); BuffViewoffset += mesh.normals.Length * 12; } if (mesh.tangents.Length > 0) { var acc = model.CreateAccessor(); var buff = model.UseBufferView(buffer, BuffViewoffset, mesh.tangents.Length * 16); acc.SetData(buff, 0, mesh.tangents.Length, DimensionType.VEC4, EncodingType.FLOAT, false); prim.SetVertexAccessor("TANGENT", acc); BuffViewoffset += mesh.tangents.Length * 16; } if (mesh.colors0.Length > 0) { var acc = model.CreateAccessor(); var buff = model.UseBufferView(buffer, BuffViewoffset, mesh.colors0.Length * 16); acc.SetData(buff, 0, mesh.colors0.Length, DimensionType.VEC4, EncodingType.FLOAT, false); prim.SetVertexAccessor("COLOR_0", acc); BuffViewoffset += mesh.colors0.Length * 16; } if (mesh.colors1.Length > 0) { var acc = model.CreateAccessor(); var buff = model.UseBufferView(buffer, BuffViewoffset, mesh.colors1.Length * 16); acc.SetData(buff, 0, mesh.colors1.Length, DimensionType.VEC4, EncodingType.FLOAT, false); prim.SetVertexAccessor("COLOR_1", acc); BuffViewoffset += mesh.colors1.Length * 16; } if (mesh.texCoords0.Length > 0) { var acc = model.CreateAccessor(); var buff = model.UseBufferView(buffer, BuffViewoffset, mesh.texCoords0.Length * 8); acc.SetData(buff, 0, mesh.texCoords0.Length, DimensionType.VEC2, EncodingType.FLOAT, false); prim.SetVertexAccessor("TEXCOORD_0", acc); BuffViewoffset += mesh.texCoords0.Length * 8; } if (mesh.texCoords1.Length > 0) { var acc = model.CreateAccessor(); var buff = model.UseBufferView(buffer, BuffViewoffset, mesh.texCoords1.Length * 8); acc.SetData(buff, 0, mesh.texCoords1.Length, DimensionType.VEC2, EncodingType.FLOAT, false); prim.SetVertexAccessor("TEXCOORD_1", acc); BuffViewoffset += mesh.texCoords1.Length * 8; } if (mesh.weightCount > 0) { if (rig != null) { { var acc = model.CreateAccessor(); var buff = model.UseBufferView(buffer, BuffViewoffset, mesh.positions.Length * 8); acc.SetData(buff, 0, mesh.positions.Length, DimensionType.VEC4, EncodingType.UNSIGNED_SHORT, false); prim.SetVertexAccessor("JOINTS_0", acc); BuffViewoffset += mesh.positions.Length * 8; } { var acc = model.CreateAccessor(); var buff = model.UseBufferView(buffer, BuffViewoffset, mesh.positions.Length * 16); acc.SetData(buff, 0, mesh.positions.Length, DimensionType.VEC4, EncodingType.FLOAT, false); prim.SetVertexAccessor("WEIGHTS_0", acc); BuffViewoffset += mesh.positions.Length * 16; } if (mesh.weightCount > 4) { { var acc = model.CreateAccessor(); var buff = model.UseBufferView(buffer, BuffViewoffset, mesh.positions.Length * 8); acc.SetData(buff, 0, mesh.positions.Length, DimensionType.VEC4, EncodingType.UNSIGNED_SHORT, false); prim.SetVertexAccessor("JOINTS_1", acc); BuffViewoffset += mesh.positions.Length * 8; } { var acc = model.CreateAccessor(); var buff = model.UseBufferView(buffer, BuffViewoffset, mesh.positions.Length * 16); acc.SetData(buff, 0, mesh.positions.Length, DimensionType.VEC4, EncodingType.FLOAT, false); prim.SetVertexAccessor("WEIGHTS_1", acc); BuffViewoffset += mesh.positions.Length * 16; } } } } { var acc = model.CreateAccessor(); var buff = model.UseBufferView(buffer, BuffViewoffset, mesh.indices.Length * 2); acc.SetData(buff, 0, mesh.indices.Length, DimensionType.SCALAR, EncodingType.UNSIGNED_SHORT, false); prim.SetIndexAccessor(acc); BuffViewoffset += mesh.indices.Length * 2; } var nod = model.UseScene(0).CreateNode(mesh.name); nod.Mesh = mes; if (rig != null && mesh.weightCount > 0) { nod.Skin = skins[0]; } var obj = new { targetNames = names }; // anonymous variable/obj mes.Extras = SharpGLTF.IO.JsonContent.Serialize(obj); for (var i = 0; i < expTargets.Count; i++) { var dict = new Dictionary <string, Accessor>(); { var acc = model.CreateAccessor(); var buff = model.UseBufferView(buffer, BuffViewoffset, mesh.positions.Length * 12); acc.SetData(buff, 0, mesh.positions.Length, DimensionType.VEC3, EncodingType.FLOAT, false); dict.Add("POSITION", acc); BuffViewoffset += mesh.positions.Length * 12; } if (mesh.normals.Length > 0) { var acc = model.CreateAccessor(); var buff = model.UseBufferView(buffer, BuffViewoffset, mesh.normals.Length * 12); acc.SetData(buff, 0, mesh.normals.Length, DimensionType.VEC3, EncodingType.FLOAT, false); dict.Add("NORMAL", acc); BuffViewoffset += mesh.normals.Length * 12; } if (mesh.tangents.Length > 0) { var acc = model.CreateAccessor(); var buff = model.UseBufferView(buffer, BuffViewoffset, mesh.tangents.Length * 12); acc.SetData(buff, 0, mesh.tangents.Length, DimensionType.VEC3, EncodingType.FLOAT, false); dict.Add("TANGENT", acc); BuffViewoffset += mesh.tangents.Length * 12; } prim.SetMorphTargetAccessors(i, dict); } } model.UseScene(0).Name = "Scene"; model.DefaultScene = model.UseScene(0); model.MergeBuffers(); return(model); }
public bool ExportAnim(Stream animStream, List <Archive> archives, FileInfo outfile, bool isGLBinary = true) { var cr2w = _wolvenkitFileService.TryReadRED4File(animStream); if (!cr2w.Chunks.Select(_ => _.Data).OfType <animAnimSet>().Any()) { return(false); } var blob = cr2w.Chunks.Select(_ => _.Data).OfType <animAnimSet>().First(); List <MemoryStream> animDataBuffers = new List <MemoryStream>(); foreach (var chk in blob.AnimationDataChunks) { UInt16 bufferIdx = chk.Buffer.Buffer.Value; var b = cr2w.Buffers[bufferIdx - 1]; animStream.Seek(b.Offset, SeekOrigin.Begin); var ms = new MemoryStream(); animStream.DecompressAndCopySegment(ms, b.DiskSize, b.MemSize); animDataBuffers.Add(ms); } RawArmature Rig = null; { ulong hash = FNV1A64HashAlgorithm.HashString(blob.Rig.DepotPath); foreach (Archive ar in archives) { if (ar.Files.ContainsKey(hash)) { var ms = new MemoryStream(); ModTools.ExtractSingleToStream(ar, hash, ms); Rig = new RIG(_wolvenkitFileService).ProcessRig(ms); break; } } } if (Rig.BoneCount < 1) { return(false); } var model = ModelRoot.CreateModel(); var skin = model.CreateSkin(); skin.BindJoints(RIG.ExportNodes(ref model, Rig).Values.ToArray()); for (int i = 0; i < blob.Animations.Count; i++) { var setEntry = (blob.Animations[i].GetReference().Data as animAnimSetEntry); var animAnimDes = (setEntry.Animation.GetReference().Data as animAnimation); if (animAnimDes.AnimationType.Value != Enums.animAnimationType.Normal) { continue; } switch (animAnimDes.AnimBuffer.GetReference().REDType) { case "animAnimationBufferSimd": { var animBuff = (animAnimDes.AnimBuffer.GetReference().Data as animAnimationBufferSimd); var bufferIdx = animBuff.DefferedBuffer.Buffer.Value; var b = cr2w.Buffers[bufferIdx - 1]; animStream.Seek(b.Offset, SeekOrigin.Begin); var defferedBuffer = new MemoryStream(); animStream.DecompressAndCopySegment(defferedBuffer, b.DiskSize, b.MemSize); SIMD.AddAnimationSIMD(ref model, animBuff, animAnimDes.Name.Value, defferedBuffer); } break; case "animAnimationBufferCompressed": { var animBuff = (animAnimDes.AnimBuffer.GetReference().Data as animAnimationBufferCompressed); var dataAddr = animBuff.DataAddress; Byte[] bytes = new Byte[dataAddr.ZeInBytes.Value]; animDataBuffers[(int)dataAddr.UnkIndex.Value].Seek(dataAddr.FsetInBytes.Value, SeekOrigin.Begin); animDataBuffers[(int)dataAddr.UnkIndex.Value].Read(bytes, 0, (int)dataAddr.ZeInBytes.Value); var defferedBuffer = new MemoryStream(bytes); SPLINE.AddAnimationSpline(ref model, animBuff, animAnimDes.Name.Value, defferedBuffer); } break; default: break; } } if (isGLBinary) { model.SaveGLB(outfile.FullName); } else { model.SaveGLTF(outfile.FullName); } return(true); }
public bool ExportMorphTargets(Stream targetStream, FileInfo outfile, List <Archive> archives, 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); } RawArmature Rig = null; MemoryStream meshbuffer = MESH.GetMeshBufferStream(targetStream, cr2w); MeshesInfo meshinfo = MESH.GetMeshesinfo(cr2w); List <RawMeshContainer> expMeshes = MESH.ContainRawMesh(meshbuffer, meshinfo, true); int subMeshC = expMeshes.Count; var buffers = cr2w.Buffers; var blob = cr2w.Chunks.Select(_ => _.Data).OfType <rendRenderMorphTargetMeshBlob>().First(); string baseMeshPath = cr2w.Chunks.Select(_ => _.Data).OfType <MorphTargetMesh>().First().BaseMesh.DepotPath; ulong hash = FNV1A64HashAlgorithm.HashString(baseMeshPath); foreach (Archive ar in archives) { if (ar.Files.ContainsKey(hash)) { var meshStream = new MemoryStream(); ModTools.ExtractSingleToStream(ar, hash, meshStream); var meshCr2w = _wolvenkitFileService.TryReadRED4File(meshStream); if (meshCr2w == null || !meshCr2w.Chunks.Select(_ => _.Data).OfType <CMesh>().Any() || !meshCr2w.Chunks.Select(_ => _.Data).OfType <rendRenderMeshBlob>().Any()) { break; } MESH.MeshBones meshBones = new MESH.MeshBones(); meshBones.boneCount = meshCr2w.Chunks.Select(_ => _.Data).OfType <CMesh>().First().BoneNames.Count; if (meshBones.boneCount != 0) // for rigid meshes { meshBones.Names = RIG.GetboneNames(meshCr2w); meshBones.WorldPosn = MESH.GetMeshBonesPosn(meshCr2w); } Rig = MESH.GetNonParentedRig(meshBones); MemoryStream ms = MESH.GetMeshBufferStream(meshStream, meshCr2w); meshinfo = MESH.GetMeshesinfo(meshCr2w); expMeshes = MESH.ContainRawMesh(ms, meshinfo, true); subMeshC = expMeshes.Count; if (meshBones.boneCount == 0) // for rigid meshes { for (int i = 0; i < expMeshes.Count; i++) { expMeshes[i].weightcount = 0; } } MESH.UpdateMeshJoints(ref expMeshes, Rig, meshBones); break; } } 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, buffers[blob.DiffsBuffer.Buffer.Value - 1].DiskSize, 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, buffers[blob.MappingBuffer.Buffer.Value - 1].DiskSize, 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, buffers[blob.TextureDiffsBuffer.Buffer.Value - 1].DiskSize, buffers[blob.TextureDiffsBuffer.Buffer.Value - 1].MemSize); } TargetsInfo targetsInfo = GetTargetInfos(cr2w, subMeshC); List <RawTargetContainer[]> expTargets = new List <RawTargetContainer[]>(); for (int i = 0; i < targetsInfo.NumTargets; i++) { UInt32[] temp_NumVertexDiffsInEachChunk = new UInt32[subMeshC]; UInt32[] temp_NumVertexDiffsMappingInEachChunk = new UInt32[subMeshC]; for (int e = 0; e < subMeshC; 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], subMeshC)); } string[] names = new string[targetsInfo.NumTargets]; for (int i = 0; i < targetsInfo.NumTargets; i++) { names[i] = targetsInfo.Names[i] + "_" + targetsInfo.RegionNames[i]; } List <MemoryStream> textureStreams = ContainTextureStreams(cr2w, texbuffer); ModelRoot model = RawTargetsToGLTF(expMeshes, expTargets, names, Rig); if (WolvenTesting.IsTesting) { return(true); } model.Extras = SharpGLTF.IO.JsonContent.Serialize(new { BaseMesh = targetsInfo.BaseMesh }); 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); }
public bool ImportTargetBaseMesh(FileInfo inGltfFile, Stream intargetStream, List <Archive> archives, string modFolder, Stream outStream = null) { var cr2w = _wolvenkitFileService.TryReadRED4File(intargetStream); if (cr2w == null || !cr2w.Chunks.Select(_ => _.Data).OfType <MorphTargetMesh>().Any() || !cr2w.Chunks.Select(_ => _.Data).OfType <rendRenderMeshBlob>().Any()) { return(false); } var blob = cr2w.Chunks.Select(_ => _.Data).OfType <MorphTargetMesh>().First(); string baseMeshPath = blob.BaseMesh.DepotPath; ulong hash = FNV1A64HashAlgorithm.HashString(baseMeshPath); baseMeshPath = Path.Combine(modFolder, baseMeshPath); if (!new FileInfo(baseMeshPath).Directory.Exists) { Directory.CreateDirectory(new FileInfo(baseMeshPath).Directory.FullName); } FileStream meshStream = new FileStream(baseMeshPath, FileMode.OpenOrCreate, FileAccess.ReadWrite); meshStream.Seek(0, SeekOrigin.Begin); if (meshStream.Length == 0) { foreach (Archive ar in archives) { if (ar.Files.ContainsKey(hash)) { ExtractSingleToStream(ar, hash, meshStream); break; } } } var renderblob = cr2w.Chunks.Select(_ => _.Data).OfType <rendRenderMorphTargetMeshBlob>().First(); for (int i = 0; i < renderblob.Header.TargetPositionDiffOffset.Count; i++) { renderblob.Header.TargetPositionDiffOffset[i].X.Value = 0f; renderblob.Header.TargetPositionDiffOffset[i].Y.Value = 0f; renderblob.Header.TargetPositionDiffOffset[i].Z.Value = 0f; } for (int i = 0; i < renderblob.Header.TargetPositionDiffScale.Count; i++) { renderblob.Header.TargetPositionDiffScale[i].X.Value = 0f; renderblob.Header.TargetPositionDiffScale[i].Y.Value = 0f; renderblob.Header.TargetPositionDiffScale[i].Z.Value = 0f; } for (int i = 0; i < renderblob.Header.TargetTextureDiffsData.Count; i++) { renderblob.Header.TargetTextureDiffsData[i] = new rendRenderMorphTargetMeshBlobTextureData(cr2w, renderblob.Header.TargetTextureDiffsData, Convert.ToString(i)); } var model = ModelRoot.Load(inGltfFile.FullName); VerifyGLTF(model); List <RawMeshContainer> Meshes = new List <RawMeshContainer>(); for (int i = 0; i < model.LogicalMeshes.Count; i++) { Meshes.Add(GltfMeshToRawContainer(model.LogicalMeshes[i])); } Vec3 max = new Vec3(Meshes[0].vertices[0].X, Meshes[0].vertices[0].Y, Meshes[0].vertices[0].Z); Vec3 min = new Vec3(Meshes[0].vertices[0].X, Meshes[0].vertices[0].Y, Meshes[0].vertices[0].Z); for (int e = 0; e < Meshes.Count; e++) { for (int i = 0; i < Meshes[e].vertices.Length; i++) { if (Meshes[e].vertices[i].X >= max.X) { max.X = Meshes[e].vertices[i].X; } if (Meshes[e].vertices[i].Y >= max.Y) { max.Y = Meshes[e].vertices[i].Y; } if (Meshes[e].vertices[i].Z >= max.Z) { max.Z = Meshes[e].vertices[i].Z; } if (Meshes[e].vertices[i].X <= min.X) { min.X = Meshes[e].vertices[i].X; } if (Meshes[e].vertices[i].Y <= min.Y) { min.Y = Meshes[e].vertices[i].Y; } if (Meshes[e].vertices[i].Z <= min.Z) { min.Z = Meshes[e].vertices[i].Z; } } } // updating bounding box blob.BoundingBox.Min.X.Value = min.X; blob.BoundingBox.Min.Y.Value = min.Y; blob.BoundingBox.Min.Z.Value = min.Z; blob.BoundingBox.Max.X.Value = max.X; blob.BoundingBox.Max.Y.Value = max.Y; blob.BoundingBox.Max.Z.Value = max.Z; Vec4 QuantScale = new Vec4((max.X - min.X) / 2, (max.Y - min.Y) / 2, (max.Z - min.Z) / 2, 0); Vec4 QuantTrans = new Vec4((max.X + min.X) / 2, (max.Y + min.Y) / 2, (max.Z + min.Z) / 2, 1); if (model.LogicalSkins.Count != 0) { string[] bones = new string[model.LogicalSkins[0].JointsCount]; for (int i = 0; i < model.LogicalSkins[0].JointsCount; i++) { bones[i] = model.LogicalSkins[0].GetJoint(i).Joint.Name; } meshStream.Seek(0, SeekOrigin.Begin); string[] meshbones = RIG.GetboneNames(_wolvenkitFileService.TryReadRED4File(meshStream)); // reset vertex joint indices according to original for (int i = 0; i < Meshes.Count; i++) { for (int e = 0; e < Meshes[i].vertices.Length; e++) { for (int eye = 0; eye < Meshes[i].weightcount; eye++) { if (Meshes[i].weights[e, eye] != 0) { bool existsInMeshBones = false; string name = bones[Meshes[i].boneindices[e, eye]]; for (UInt16 t = 0; t < meshbones.Length; t++) { if (name == meshbones[t]) { Meshes[i].boneindices[e, eye] = t; existsInMeshBones = true; } } if (!existsInMeshBones) { throw new Exception("One or more vertices in submesh: " + Meshes[i].name + " was weight Painted to bone: " + name + " Which Doesn't Exist in the provided .mesh file"); } } else { if (Meshes[i].boneindices[e, eye] > (meshbones.Length - 1)) { Meshes[i].boneindices[e, eye] = 0; } } } } } } List <Re4MeshContainer> expMeshes = new List <Re4MeshContainer>(); for (int i = 0; i < Meshes.Count; i++) { expMeshes.Add(RawMeshToRE4Mesh(Meshes[i], QuantScale, QuantTrans)); } MemoryStream meshBuffer = new MemoryStream(); MeshesInfo meshesInfo = BufferWriter(expMeshes, ref meshBuffer); meshesInfo.qScale = QuantScale; meshesInfo.qTrans = QuantTrans; MemoryStream ms = GetEditedCr2wFile(cr2w, meshesInfo, meshBuffer); ms.Seek(0, SeekOrigin.Begin); if (outStream != null) { ms.CopyTo(outStream); } else { intargetStream.SetLength(0); ms.CopyTo(intargetStream); } meshStream.Seek(0, SeekOrigin.Begin); return(ImportMesh(inGltfFile, meshStream)); }
public static ModelRoot RawMeshesToGLTF(List <RawMeshContainer> meshes, RawArmature Rig) { var model = ModelRoot.CreateModel(); var mat = model.CreateMaterial("Default"); mat.WithPBRMetallicRoughness().WithDefault(); mat.DoubleSided = true; List <Skin> skins = new List <Skin>(); if (Rig != null) { var skin = model.CreateSkin(); skin.BindJoints(RIG.ExportNodes(ref model, Rig).Values.ToArray()); skins.Add(skin); } var ms = new MemoryStream(); var bw = new BinaryWriter(ms); foreach (var mesh in meshes) { for (int i = 0; i < mesh.vertices.Length; i++) { bw.Write(mesh.vertices[i].X); bw.Write(mesh.vertices[i].Y); bw.Write(mesh.vertices[i].Z); } for (int i = 0; i < mesh.normals.Length; i++) { bw.Write(mesh.normals[i].X); bw.Write(mesh.normals[i].Y); bw.Write(mesh.normals[i].Z); } for (int i = 0; i < mesh.tangents.Length; i++) { bw.Write(mesh.tangents[i].X); bw.Write(mesh.tangents[i].Y); bw.Write(mesh.tangents[i].Z); bw.Write(mesh.tangents[i].W); } for (int i = 0; i < mesh.colors.Length; i++) { bw.Write(mesh.colors[i].X); bw.Write(mesh.colors[i].Y); bw.Write(mesh.colors[i].Z); bw.Write(mesh.colors[i].W); } for (int i = 0; i < mesh.tx0coords.Length; i++) { bw.Write(mesh.tx0coords[i].X); bw.Write(mesh.tx0coords[i].Y); } for (int i = 0; i < mesh.tx1coords.Length; i++) { bw.Write(mesh.tx1coords[i].X); bw.Write(mesh.tx1coords[i].Y); } if (mesh.weightcount > 0) { if (Rig != null) { for (int i = 0; i < mesh.vertices.Length; i++) { bw.Write(mesh.boneindices[i, 0]); bw.Write(mesh.boneindices[i, 1]); bw.Write(mesh.boneindices[i, 2]); bw.Write(mesh.boneindices[i, 3]); } for (int i = 0; i < mesh.vertices.Length; i++) { bw.Write(mesh.weights[i, 0]); bw.Write(mesh.weights[i, 1]); bw.Write(mesh.weights[i, 2]); bw.Write(mesh.weights[i, 3]); } if (mesh.weightcount > 4) { for (int i = 0; i < mesh.vertices.Length; i++) { bw.Write(mesh.boneindices[i, 4]); bw.Write(mesh.boneindices[i, 5]); bw.Write(mesh.boneindices[i, 6]); bw.Write(mesh.boneindices[i, 7]); } for (int i = 0; i < mesh.vertices.Length; i++) { bw.Write(mesh.weights[i, 4]); bw.Write(mesh.weights[i, 5]); bw.Write(mesh.weights[i, 6]); bw.Write(mesh.weights[i, 7]); } } } } for (int i = 0; i < mesh.indices.Length; i += 3) { bw.Write(Convert.ToUInt16(mesh.indices[i + 1])); bw.Write(Convert.ToUInt16(mesh.indices[i + 0])); bw.Write(Convert.ToUInt16(mesh.indices[i + 2])); } if (mesh.extraExist) { for (int i = 0; i < mesh.vertices.Length; i++) { bw.Write(mesh.extradata[i].X); bw.Write(mesh.extradata[i].Y); bw.Write(mesh.extradata[i].Z); } } } var buffer = model.UseBuffer(ms.ToArray()); int BuffViewoffset = 0; foreach (var mesh in meshes) { var mes = model.CreateMesh(mesh.name); var prim = mes.CreatePrimitive(); prim.Material = mat; { var acc = model.CreateAccessor(); var buff = model.UseBufferView(buffer, BuffViewoffset, mesh.vertices.Length * 12); acc.SetData(buff, 0, mesh.vertices.Length, DimensionType.VEC3, EncodingType.FLOAT, false); prim.SetVertexAccessor("POSITION", acc); BuffViewoffset += mesh.vertices.Length * 12; } if (mesh.normals.Length > 0) { var acc = model.CreateAccessor(); var buff = model.UseBufferView(buffer, BuffViewoffset, mesh.normals.Length * 12); acc.SetData(buff, 0, mesh.normals.Length, DimensionType.VEC3, EncodingType.FLOAT, false); prim.SetVertexAccessor("NORMAL", acc); BuffViewoffset += mesh.normals.Length * 12; } if (mesh.tangents.Length > 0) { var acc = model.CreateAccessor(); var buff = model.UseBufferView(buffer, BuffViewoffset, mesh.tangents.Length * 16); acc.SetData(buff, 0, mesh.tangents.Length, DimensionType.VEC4, EncodingType.FLOAT, false); prim.SetVertexAccessor("TANGENT", acc); BuffViewoffset += mesh.tangents.Length * 16; } if (mesh.colors.Length > 0) { var acc = model.CreateAccessor(); var buff = model.UseBufferView(buffer, BuffViewoffset, mesh.colors.Length * 16); acc.SetData(buff, 0, mesh.colors.Length, DimensionType.VEC4, EncodingType.FLOAT, false); prim.SetVertexAccessor("COLOR_0", acc); BuffViewoffset += mesh.colors.Length * 16; } if (mesh.tx0coords.Length > 0) { var acc = model.CreateAccessor(); var buff = model.UseBufferView(buffer, BuffViewoffset, mesh.tx0coords.Length * 8); acc.SetData(buff, 0, mesh.tx0coords.Length, DimensionType.VEC2, EncodingType.FLOAT, false); prim.SetVertexAccessor("TEXCOORD_0", acc); BuffViewoffset += mesh.tx0coords.Length * 8; } if (mesh.tx1coords.Length > 0) { var acc = model.CreateAccessor(); var buff = model.UseBufferView(buffer, BuffViewoffset, mesh.tx1coords.Length * 8); acc.SetData(buff, 0, mesh.tx1coords.Length, DimensionType.VEC2, EncodingType.FLOAT, false); prim.SetVertexAccessor("TEXCOORD_1", acc); BuffViewoffset += mesh.tx1coords.Length * 8; } if (mesh.weightcount > 0) { if (Rig != null) { { var acc = model.CreateAccessor(); var buff = model.UseBufferView(buffer, BuffViewoffset, mesh.vertices.Length * 8); acc.SetData(buff, 0, mesh.vertices.Length, DimensionType.VEC4, EncodingType.UNSIGNED_SHORT, false); prim.SetVertexAccessor("JOINTS_0", acc); BuffViewoffset += mesh.vertices.Length * 8; } { var acc = model.CreateAccessor(); var buff = model.UseBufferView(buffer, BuffViewoffset, mesh.vertices.Length * 16); acc.SetData(buff, 0, mesh.vertices.Length, DimensionType.VEC4, EncodingType.FLOAT, false); prim.SetVertexAccessor("WEIGHTS_0", acc); BuffViewoffset += mesh.vertices.Length * 16; } if (mesh.weightcount > 4) { { var acc = model.CreateAccessor(); var buff = model.UseBufferView(buffer, BuffViewoffset, mesh.vertices.Length * 8); acc.SetData(buff, 0, mesh.vertices.Length, DimensionType.VEC4, EncodingType.UNSIGNED_SHORT, false); prim.SetVertexAccessor("JOINTS_1", acc); BuffViewoffset += mesh.vertices.Length * 8; } { var acc = model.CreateAccessor(); var buff = model.UseBufferView(buffer, BuffViewoffset, mesh.vertices.Length * 16); acc.SetData(buff, 0, mesh.vertices.Length, DimensionType.VEC4, EncodingType.FLOAT, false); prim.SetVertexAccessor("WEIGHTS_1", acc); BuffViewoffset += mesh.vertices.Length * 16; } } } } { var acc = model.CreateAccessor(); var buff = model.UseBufferView(buffer, BuffViewoffset, mesh.indices.Length * 2); acc.SetData(buff, 0, mesh.indices.Length, DimensionType.SCALAR, EncodingType.UNSIGNED_SHORT, false); prim.SetIndexAccessor(acc); BuffViewoffset += mesh.indices.Length * 2; } var nod = model.UseScene(0).CreateNode(mesh.name); nod.Mesh = mes; if (Rig != null && mesh.weightcount > 0) { nod.Skin = skins[0]; } if (mesh.extraExist) { string[] arr = { "GarmentSupport" }; var obj = new { appNames = mesh.appNames, materialNames = mesh.materialNames, targetNames = arr }; mes.Extras = SharpGLTF.IO.JsonContent.Serialize(obj); } else { var obj = new { appNames = mesh.appNames, materialNames = mesh.materialNames }; mes.Extras = SharpGLTF.IO.JsonContent.Serialize(obj); } if (mesh.extraExist) { var acc = model.CreateAccessor(); var buff = model.UseBufferView(buffer, BuffViewoffset, mesh.extradata.Length * 12); acc.SetData(buff, 0, mesh.extradata.Length, DimensionType.VEC3, EncodingType.FLOAT, false); var dict = new Dictionary <string, Accessor>(); dict.Add("POSITION", acc); prim.SetMorphTargetAccessors(0, dict); BuffViewoffset += mesh.extradata.Length * 12; } } model.UseScene(0).Name = "Scene"; model.DefaultScene = model.UseScene(0); model.MergeBuffers(); return(model); }
public bool ExportMultiMeshWithRig(List <Stream> meshStreamS, List <Stream> rigStreamS, FileInfo outfile, bool LodFilter = true, bool isGLBinary = true) { List <RawArmature> Rigs = new List <RawArmature>(); rigStreamS = rigStreamS.OrderByDescending(r => r.Length).ToList(); // not so smart hacky method to get bodybase rigs on top/ orderby descending for (int r = 0; r < rigStreamS.Count; r++) { RawArmature Rig = _rig.ProcessRig(rigStreamS[r]); Rigs.Add(Rig); } RawArmature expRig = RIG.CombineRigs(Rigs); List <RawMeshContainer> expMeshes = new List <RawMeshContainer>(); for (int m = 0; m < meshStreamS.Count; m++) { var cr2w = _wolvenkitFileService.TryReadRED4File(meshStreamS[m]); if (cr2w == null || !cr2w.Chunks.Select(_ => _.Data).OfType <CMesh>().Any() || !cr2w.Chunks.Select(_ => _.Data).OfType <rendRenderMeshBlob>().Any()) { continue; } MemoryStream ms = GetMeshBufferStream(meshStreamS[m], cr2w); MeshesInfo meshinfo = GetMeshesinfo(cr2w); MeshBones bones = new MeshBones(); CMesh cmesh = cr2w.Chunks.Select(_ => _.Data).OfType <CMesh>().First(); if (cmesh.BoneNames.Count != 0) // for rigid meshes { bones.Names = RIG.GetboneNames(cr2w); bones.WorldPosn = GetMeshBonesPosn(cr2w); } List <RawMeshContainer> Meshes = ContainRawMesh(ms, meshinfo, LodFilter); for (int i = 0; i < Meshes.Count; i++) { Meshes[i].name = m + "_" + Meshes[i].name; if (cmesh.BoneNames.Count == 0) // for rigid meshes { Meshes[i].weightcount = 0; } } UpdateMeshJoints(ref Meshes, expRig, bones); expMeshes.AddRange(Meshes); } ModelRoot model = RawMeshesToGLTF(expMeshes, expRig); if (isGLBinary) { model.SaveGLB(outfile.FullName); } else { model.SaveGLTF(outfile.FullName); } for (int i = 0; i < meshStreamS.Count; i++) { meshStreamS[i].Dispose(); meshStreamS[i].Close(); } for (int i = 0; i < rigStreamS.Count; i++) { rigStreamS[i].Dispose(); rigStreamS[i].Close(); } return(true); }
public MESH(Red4ParserService wolvenkitFileService, RIG rig) { _wolvenkitFileService = wolvenkitFileService; _rig = rig; }
public bool ExportMesh(Stream meshStream, FileInfo outfile, bool LodFilter = true, bool isGLBinary = true) { var cr2w = _wolvenkitFileService.TryReadRED4File(meshStream); if (cr2w == null || !cr2w.Chunks.Select(_ => _.Data).OfType <CMesh>().Any()) { return(false); } if (!cr2w.Chunks.Select(_ => _.Data).OfType <rendRenderMeshBlob>().Any()) { return(WriteFakeMeshToFile()); } MeshBones meshBones = new MeshBones(); meshBones.boneCount = cr2w.Chunks.Select(_ => _.Data).OfType <CMesh>().First().BoneNames.Count; if (meshBones.boneCount != 0) // for rigid meshes { meshBones.Names = RIG.GetboneNames(cr2w); meshBones.WorldPosn = GetMeshBonesPosn(cr2w); } RawArmature Rig = GetNonParentedRig(meshBones); MemoryStream ms = GetMeshBufferStream(meshStream, cr2w); MeshesInfo meshinfo = GetMeshesinfo(cr2w); List <RawMeshContainer> expMeshes = ContainRawMesh(ms, meshinfo, LodFilter); if (meshBones.boneCount == 0) // for rigid meshes { for (int i = 0; i < expMeshes.Count; i++) { expMeshes[i].weightcount = 0; } } UpdateMeshJoints(ref expMeshes, Rig, meshBones); ModelRoot model = RawMeshesToGLTF(expMeshes, Rig); WriteMeshToFile(); meshStream.Dispose(); meshStream.Close(); return(true); bool WriteFakeMeshToFile() { if (WolvenTesting.IsTesting) { return(true); } if (isGLBinary) { ModelRoot.CreateModel().SaveGLB(outfile.FullName); } else { ModelRoot.CreateModel().SaveGLTF(outfile.FullName); } return(true); } void WriteMeshToFile() { if (WolvenTesting.IsTesting) { return; } if (isGLBinary) { model.SaveGLB(outfile.FullName); } else { model.SaveGLTF(outfile.FullName); } } }
public AnyStateAnimation(RIG rig, string name, params string[] higherPrio) { AnimationRig = rig; Name = name; HigherPrio = higherPrio; }
public bool ExportAnim(Stream animStream, List <Archive> archives, FileInfo outfile, bool isGLBinary = true) { var cr2w = _wolvenkitFileService.ReadRed4File(animStream); if (cr2w == null || cr2w.RootChunk is not animAnimSet blob) { return(false); } var animDataBuffers = new List <MemoryStream>(); foreach (var chk in blob.AnimationDataChunks) { var ms = new MemoryStream(); ms.Write(chk.Buffer.Buffer.GetBytes()); animDataBuffers.Add(ms); } var Rig = new RawArmature(); var hash = FNV1A64HashAlgorithm.HashString(blob.Rig.DepotPath); foreach (var ar in archives) { if (ar.Files.ContainsKey(hash)) { var ms = new MemoryStream(); ModTools.ExtractSingleToStream(ar, hash, ms); Rig = RIG.ProcessRig(_wolvenkitFileService.ReadRed4File(ms)); break; } } if (Rig is null) { return(false); } if (Rig.BoneCount < 1) { return(false); } var model = ModelRoot.CreateModel(); var skin = model.CreateSkin(); skin.BindJoints(RIG.ExportNodes(ref model, Rig).Values.ToArray()); for (var i = 0; i < blob.Animations.Count; i++) { var setEntry = blob.Animations[i].Chunk; var animAnimDes = setEntry.Animation.Chunk; if (animAnimDes.AnimationType.Value != Enums.animAnimationType.Normal) { continue; } if (animAnimDes.AnimBuffer.Chunk is animAnimationBufferSimd) { var animBuff = (animAnimDes.AnimBuffer.Chunk as animAnimationBufferSimd); MemoryStream defferedBuffer; if (animBuff.InplaceCompressedBuffer != null) { defferedBuffer = new MemoryStream(animBuff.InplaceCompressedBuffer.Buffer.GetBytes()); } else { defferedBuffer = new MemoryStream(animBuff.DefferedBuffer.Buffer.GetBytes()); } defferedBuffer.Seek(0, SeekOrigin.Begin); SIMD.AddAnimationSIMD(ref model, animBuff, animAnimDes.Name, defferedBuffer, animAnimDes); } else if (animAnimDes.AnimBuffer.Chunk is animAnimationBufferCompressed) { var animBuff = (animAnimDes.AnimBuffer.Chunk as animAnimationBufferCompressed); var defferedBuffer = new MemoryStream(); if (animBuff.InplaceCompressedBuffer != null) { defferedBuffer = new MemoryStream(animBuff.InplaceCompressedBuffer.Buffer.GetBytes()); } else if (animBuff.DataAddress != null) { var dataAddr = animBuff.DataAddress; var bytes = new byte[dataAddr.ZeInBytes]; animDataBuffers[(int)((uint)dataAddr.UnkIndex)].Seek(dataAddr.FsetInBytes, SeekOrigin.Begin); animDataBuffers[(int)((uint)dataAddr.UnkIndex)].Read(bytes, 0, (int)((uint)dataAddr.ZeInBytes)); defferedBuffer = new MemoryStream(bytes); } else if (animBuff.DefferedBuffer.Buffer.MemSize > 0) { defferedBuffer.Write(animBuff.DefferedBuffer.Buffer.GetBytes()); } defferedBuffer.Seek(0, SeekOrigin.Begin); SPLINE.AddAnimationSpline(ref model, animBuff, animAnimDes.Name, defferedBuffer, animAnimDes); } } if (isGLBinary) { model.SaveGLB(outfile.FullName); } else { model.SaveGLTF(outfile.FullName); } return(true); }
public AnyStateAnimation(RIG rig, string name) { this.AnimationRig = rig; this.Name = name; }