public static RawArmature GetNonParentedRig(MeshBones meshBones)
        {
            if (meshBones.boneCount != 0)    // for rigid meshes
            {
                RawArmature Rig = new RawArmature();
                Rig.BoneCount  = meshBones.boneCount + 1;
                Rig.LocalPosn  = new Vec3[Rig.BoneCount];
                Rig.LocalRot   = new System.Numerics.Quaternion[Rig.BoneCount];
                Rig.LocalScale = new Vec3[Rig.BoneCount];
                Rig.Parent     = new Int16[Rig.BoneCount];
                Rig.Names      = new string[Rig.BoneCount];

                Rig.Parent[0]     = -1;
                Rig.Names[0]      = "WolvenKit_Root";
                Rig.LocalPosn[0]  = new Vec3(0f, 0f, 0f);
                Rig.LocalRot[0]   = new System.Numerics.Quaternion(0f, 0f, 0f, 1f);
                Rig.LocalScale[0] = new Vec3(1f, 1f, 1f);

                for (int i = 0; i < Rig.BoneCount - 1; i++)
                {
                    Rig.LocalPosn[i + 1]  = meshBones.WorldPosn[i];
                    Rig.Names[i + 1]      = meshBones.Names[i];
                    Rig.LocalRot[i + 1]   = new System.Numerics.Quaternion(-0.707107f, 0f, 0f, 0.707107f);
                    Rig.LocalScale[i + 1] = new Vec3(1f, 1f, 1f);
                    Rig.Parent[i + 1]     = 0;
                }
                return(Rig);
            }
            return(null);
        }
        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 static void UpdateMeshJoints(ref List <RawMeshContainer> Meshes, RawArmature Rig, MeshBones Bones)
 {
     // updating mesh bone indexes
     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++)
             {
                 bool found = false;
                 for (UInt16 r = 0; r < Rig.BoneCount; r++)
                 {
                     if (Rig.Names[r] == Bones.Names[Meshes[i].boneindices[e, eye]])
                     {
                         Meshes[i].boneindices[e, eye] = r;
                         found = true;
                         break;
                     }
                 }
                 if (!found)
                 {
                     throw new Exception("Bone: " + Bones.Names[Meshes[i].boneindices[e, eye]] + " is not present in the Provided .rig(s).\nInput .rig(s) are incompatible or incomplete, Please provide a/more compatible .rig(s)\nTIP: 1. For body .rig(s) provide {BodyType}_base_deformations.rig instead of {BodyType}_base.rig.\n2. if Input .mesh(s) contains any dangle/physics bones, provide the compatible dangle.rig also.\n");
                 }
             }
         }
     }
 }
        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);
                }
            }
        }