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);
        }
Exemple #2
0
        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);
        }
Exemple #3
0
        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);
        }
Exemple #4
0
        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 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 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);
                }
            }
        }