Ejemplo n.º 1
0
        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);
        }
Ejemplo n.º 2
0
 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");
                 }
             }
         }
     }
 }
Ejemplo n.º 3
0
        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);
        }
Ejemplo n.º 4
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);
        }
Ejemplo n.º 5
0
        public static Dictionary <int, Node> ExportNodes(ref ModelRoot model, RawArmature srcBones)
        {
            var bonesMapping = new Dictionary <int, Node>();
            var armature     = model.UseScene(0).CreateNode("Armature");

            for (var i = 0; i < srcBones.BoneCount; i++)
            {
                if (srcBones.Parent[i] > -1)
                {
                    var bone = bonesMapping[srcBones.Parent[i]].CreateNode(srcBones.Names[i]);
                    if (srcBones.AposeLSExits)
                    {
                        var s = new Vec3(srcBones.AposeLSScale[i].X, srcBones.AposeLSScale[i].Y, srcBones.AposeLSScale[i].Z);
                        var r = new Quat(srcBones.AposeLSRot[i].X, srcBones.AposeLSRot[i].Y, srcBones.AposeLSRot[i].Z, srcBones.AposeLSRot[i].W);
                        var t = new Vec3(srcBones.AposeLSTrans[i].X, srcBones.AposeLSTrans[i].Y, srcBones.AposeLSTrans[i].Z);

                        bone.WithLocalTranslation(t).WithLocalRotation(r).WithLocalScale(s);
                    }
                    else
                    {
                        var s = new Vec3(srcBones.LocalScale[i].X, srcBones.LocalScale[i].Y, srcBones.LocalScale[i].Z);
                        var r = new Quat(srcBones.LocalRot[i].X, srcBones.LocalRot[i].Y, srcBones.LocalRot[i].Z, srcBones.LocalRot[i].W);
                        var t = new Vec3(srcBones.LocalPosn[i].X, srcBones.LocalPosn[i].Y, srcBones.LocalPosn[i].Z);

                        bone.WithLocalTranslation(t).WithLocalRotation(r).WithLocalScale(s);
                    }
                    bonesMapping[i] = bone;
                }
                else
                {
                    var root = armature.CreateNode(srcBones.Names[i]);
                    if (srcBones.AposeLSExits)
                    {
                        var s = new Vec3(srcBones.AposeLSScale[i].X, srcBones.AposeLSScale[i].Y, srcBones.AposeLSScale[i].Z);
                        var r = new Quat(srcBones.AposeLSRot[i].X, srcBones.AposeLSRot[i].Y, srcBones.AposeLSRot[i].Z, srcBones.AposeLSRot[i].W);
                        var t = new Vec3(srcBones.AposeLSTrans[i].X, srcBones.AposeLSTrans[i].Y, srcBones.AposeLSTrans[i].Z);
                        root.WithLocalTranslation(t).WithLocalRotation(r).WithLocalScale(s);
                    }
                    else
                    {
                        var s = new Vec3(srcBones.LocalScale[i].X, srcBones.LocalScale[i].Y, srcBones.LocalScale[i].Z);
                        var r = new Quat(srcBones.LocalRot[i].X, srcBones.LocalRot[i].Y, srcBones.LocalRot[i].Z, srcBones.LocalRot[i].W);
                        var t = new Vec3(srcBones.LocalPosn[i].X, srcBones.LocalPosn[i].Y, srcBones.LocalPosn[i].Z);

                        root.WithLocalTranslation(t).WithLocalRotation(r).WithLocalScale(s);
                    }
                    bonesMapping[i] = root;
                }
            }

            return(bonesMapping);
        }
Ejemplo n.º 6
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);
            }

            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);
        }
Ejemplo n.º 7
0
        public static RawArmature ProcessRig(CR2WFile cr2w)
        {
            if (cr2w == null || cr2w.RootChunk is not animRig animrig)
            {
                return(null);
            }

            var Rig = new RawArmature
            {
                BoneCount = animrig.BoneNames.Count
            };

            Rig.Names = new string[Rig.BoneCount];
            for (var i = 0; i < animrig.BoneNames.Count; i++)
            {
                Rig.Names[i] = animrig.BoneNames[i];
            }

            Rig.Parent = new short[Rig.BoneCount];
            for (var i = 0; i < animrig.Unk1.Count; i++)
            {
                Rig.Parent[i] = animrig.Unk1[i];
            }

            Rig.LocalPosn = new Vec3[Rig.BoneCount];
            for (var i = 0; i < Rig.BoneCount; i++)
            {
                var v = new Vec3(animrig.Unk2[i][0].X, animrig.Unk2[i][0].Y, animrig.Unk2[i][0].Z);
                Rig.LocalPosn[i] = new Vec3(v.X, v.Z, -v.Y);
            }

            Rig.LocalRot = new Quat[Rig.BoneCount];

            for (var i = 0; i < Rig.BoneCount; i++)
            {
                var q = new Quat(animrig.Unk2[i][1].X, animrig.Unk2[i][1].Y, animrig.Unk2[i][1].Z, animrig.Unk2[i][1].W);
                Rig.LocalRot[i] = new Quat(q.X, q.Z, -q.Y, q.W);
            }

            Rig.LocalScale = new Vec3[Rig.BoneCount];
            for (var i = 0; i < Rig.BoneCount; i++)
            {
                var v = new Vec3(animrig.Unk2[i][2].X, animrig.Unk2[i][2].Y, animrig.Unk2[i][2].Z);
                Rig.LocalScale[i] = new Vec3(v.X, v.Y, v.Z);
            }

            // if AposeWorld/AposeMS Exists then..... this can be done better i guess...
            if (cr2w.RootChunk is animRig aRig)
            {
                if (aRig.APoseMS.Count != 0)
                {
                    Rig.AposeMSExits = true;
                    Rig.AposeMSTrans = new Vec3[Rig.BoneCount];
                    Rig.AposeMSRot   = new Quat[Rig.BoneCount];
                    Rig.AposeMSScale = new Vec3[Rig.BoneCount];

                    for (var i = 0; i < Rig.BoneCount; i++)
                    {
                        float x = aRig.APoseMS[i].Translation.X;
                        float y = aRig.APoseMS[i].Translation.Y;
                        float z = aRig.APoseMS[i].Translation.Z;
                        Rig.AposeMSTrans[i] = new Vec3(x, z, -y);
                        float I = aRig.APoseMS[i].Rotation.I;
                        float J = aRig.APoseMS[i].Rotation.J;
                        float K = aRig.APoseMS[i].Rotation.K;
                        float R = aRig.APoseMS[i].Rotation.R;
                        Rig.AposeMSRot[i] = new Quat(I, K, -J, R);
                        float t = aRig.APoseMS[i].Scale.X;
                        float u = aRig.APoseMS[i].Scale.Y;
                        float v = aRig.APoseMS[i].Scale.Z;
                        Rig.AposeMSScale[i] = new Vec3(t, v, u);
                    }
                }

                // not sure how APose works or how the matrix multiplication will be, maybe its a recursive mul
                if (aRig.APoseLS.Count != 0)
                {
                    Rig.AposeLSExits = true;
                    Rig.AposeLSTrans = new Vec3[Rig.BoneCount];
                    Rig.AposeLSRot   = new Quat[Rig.BoneCount];
                    Rig.AposeLSScale = new Vec3[Rig.BoneCount];

                    for (var i = 0; i < Rig.BoneCount; i++)
                    {
                        float x = aRig.APoseLS[i].Translation.X;
                        float y = aRig.APoseLS[i].Translation.Y;
                        float z = aRig.APoseLS[i].Translation.Z;
                        Rig.AposeLSTrans[i] = new Vec3(x, z, -y);
                        float I = aRig.APoseLS[i].Rotation.I;
                        float J = aRig.APoseLS[i].Rotation.J;
                        float K = aRig.APoseLS[i].Rotation.K;
                        float R = aRig.APoseLS[i].Rotation.R;
                        Rig.AposeLSRot[i] = new Quat(I, K, -J, R);
                        float t = aRig.APoseLS[i].Scale.X;
                        float u = aRig.APoseLS[i].Scale.Y;
                        float v = aRig.APoseLS[i].Scale.Z;
                        Rig.AposeLSScale[i] = new Vec3(t, v, u);
                    }
                }
            }

            var baseTendencyBoneNames = new string[] { "Root", "Hips", "Spine", "LeftUpLeg", "RightUpLeg", "Spine1", "LeftLeg", "RightLeg", "Spine2", "LeftFoot", "RightFoot", "Spine3",
                                                       "LeftShoulder", "RightShoulder", "Neck", "LeftArm", "RightArm", "Neck1", "LeftForeArm", "RightForeArm", "Head" };

            Rig.baseTendencyCount = 0;
            for (var i = 0; i < baseTendencyBoneNames.Length; i++)
            {
                if (Rig.Names.Contains(baseTendencyBoneNames[i]))
                {
                    Rig.baseTendencyCount++;
                }
            }
            return(Rig);
        }
Ejemplo n.º 8
0
        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);
        }
Ejemplo n.º 9
0
        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);
        }
Ejemplo n.º 10
0
        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);
        }
Ejemplo n.º 11
0
        public static RawArmature CombineRigs(List <RawArmature> rigs)
        {
            rigs = rigs.OrderByDescending(_ => _.BoneCount).ToList();
            rigs = rigs.OrderByDescending(_ => _.baseTendencyCount).ToList();

            List <string> Names = new List <string>();

            List <Int16> Parent     = new List <Int16>();
            int          BoneCount  = 0;
            List <Vec3>  LocalPosn  = new List <Vec3>();
            List <Quat>  LocalRot   = new List <Quat>();
            List <Vec3>  LocalScale = new List <Vec3>();

            for (int i = 0; i < rigs.Count; i++)
            {
                for (int e = 0; e < rigs[i].BoneCount; e++)
                {
                    bool found = false;
                    for (int eye = 0; eye < BoneCount; eye++)
                    {
                        if (Names[eye] == rigs[i].Names[e])
                        {
                            found = true;
                            break;
                        }
                    }
                    if (!found)
                    {
                        Names.Add(rigs[i].Names[e]);
                        if (rigs[i].AposeLSExits)
                        {
                            LocalPosn.Add(rigs[i].AposeLSTrans[e]);
                            LocalScale.Add(rigs[i].AposeLSScale[e]);
                            LocalRot.Add(rigs[i].AposeLSRot[e]);
                        }
                        else
                        {
                            LocalPosn.Add(rigs[i].LocalPosn[e]);
                            LocalScale.Add(rigs[i].LocalScale[e]);
                            LocalRot.Add(rigs[i].LocalRot[e]);
                        }
                        BoneCount++;
                    }
                }
            }
            // this rig merging is gonna break if someone tries to merge rigs not having a "Root" bone, generally seen with weapons etc.
            Parent.Add(-1);                     // assuming at i = 0 is always "Root" bone
            for (int i = 1; i < BoneCount; i++) // i = 1, assuming at i = 0 is always "Root" bone
            {
                bool   found      = false;
                string parentName = string.Empty;

                for (int e = 0; e < rigs.Count; e++)
                {
                    for (int eye = 0; eye < rigs[e].BoneCount; eye++)
                    {
                        if (Names[i] == rigs[e].Names[eye])
                        {
                            found      = true;
                            parentName = rigs[e].Names[rigs[e].Parent[eye]];
                            break;
                        }
                    }
                    if (found)
                    {
                        break;
                    }
                }
                for (Int16 r = 0; r < BoneCount; r++)
                {
                    if (parentName == Names[r])
                    {
                        Parent.Add(r);
                        break;
                    }
                }
            }

            RawArmature CombinedRig = new RawArmature();

            CombinedRig.BoneCount    = BoneCount;
            CombinedRig.Names        = Names.ToArray();
            CombinedRig.Parent       = Parent.ToArray();
            CombinedRig.LocalPosn    = LocalPosn.ToArray();
            CombinedRig.LocalScale   = LocalScale.ToArray();
            CombinedRig.LocalRot     = LocalRot.ToArray();
            CombinedRig.AposeLSExits = false;
            CombinedRig.AposeMSExits = false;

            return(CombinedRig);
        }
Ejemplo n.º 12
0
        public RawArmature ProcessRig(Stream fs)
        {
            BinaryReader br = new BinaryReader(fs);

            var cr2w = _wolvenkitFileService.TryReadRED4File(fs);

            if (cr2w == null || !cr2w.Chunks.Select(_ => _.Data).OfType <animRig>().Any())
            {
                return(new RawArmature());
            }
            RawArmature Rig = new RawArmature();

            Rig.Names     = GetboneNames(cr2w);
            Rig.BoneCount = Rig.Names.Length;

            var animrig = cr2w.Chunks.Select(_ => _.Data).OfType <animRig>().First();

            Rig.Parent = GetboneParents(animrig);

            Rig.LocalPosn = new Vec3[Rig.BoneCount];

            for (int i = 0; i < Rig.BoneCount; i++)
            {
                Vec3 v = new Vec3(animrig.Unk2[i][0].X.Value, animrig.Unk2[i][0].Y.Value, animrig.Unk2[i][0].Z.Value);
                Rig.LocalPosn[i] = new Vec3(v.X, v.Z, -v.Y);
            }

            Rig.LocalRot = new Quat[Rig.BoneCount];

            for (int i = 0; i < Rig.BoneCount; i++)
            {
                Quat q = new Quat(animrig.Unk2[i][1].X.Value, animrig.Unk2[i][1].Y.Value, animrig.Unk2[i][1].Z.Value, animrig.Unk2[i][1].W.Value);
                Rig.LocalRot[i] = new Quat(q.X, q.Z, -q.Y, q.W);
            }

            Rig.LocalScale = new Vec3[Rig.BoneCount];
            for (int i = 0; i < Rig.BoneCount; i++)
            {
                Vec3 v = new Vec3(animrig.Unk2[i][2].X.Value, animrig.Unk2[i][2].Y.Value, animrig.Unk2[i][2].Z.Value);
                Rig.LocalScale[i] = new Vec3(v.X, v.Y, v.Z);
            }

            // if AposeWorld/AposeMS Exists then..... this can be done better i guess...
            if ((cr2w.Chunks[0].Data as animRig).APoseMS.Count != 0)
            {
                Rig.AposeMSExits = true;
                Rig.AposeMSTrans = new Vec3[Rig.BoneCount];
                Rig.AposeMSRot   = new Quat[Rig.BoneCount];
                Rig.AposeMSScale = new Vec3[Rig.BoneCount];

                for (int i = 0; i < Rig.BoneCount; i++)
                {
                    float x = (cr2w.Chunks[0].Data as animRig).APoseMS[i].Translation.X.Value;
                    float y = (cr2w.Chunks[0].Data as animRig).APoseMS[i].Translation.Y.Value;
                    float z = (cr2w.Chunks[0].Data as animRig).APoseMS[i].Translation.Z.Value;
                    Rig.AposeMSTrans[i] = new Vec3(x, z, -y);
                    float I = (cr2w.Chunks[0].Data as animRig).APoseMS[i].Rotation.I.Value;
                    float J = (cr2w.Chunks[0].Data as animRig).APoseMS[i].Rotation.J.Value;
                    float K = (cr2w.Chunks[0].Data as animRig).APoseMS[i].Rotation.K.Value;
                    float R = (cr2w.Chunks[0].Data as animRig).APoseMS[i].Rotation.R.Value;
                    Rig.AposeMSRot[i] = new Quat(I, K, -J, R);
                    float t = (cr2w.Chunks[0].Data as animRig).APoseMS[i].Scale.X.Value;
                    float u = (cr2w.Chunks[0].Data as animRig).APoseMS[i].Scale.Y.Value;
                    float v = (cr2w.Chunks[0].Data as animRig).APoseMS[i].Scale.Z.Value;
                    Rig.AposeMSScale[i] = new Vec3(t, v, u);
                }
            }

            // not sure how APose works or how the matrix multiplication will be, maybe its a recursive mul
            if ((cr2w.Chunks[0].Data as animRig).APoseLS.Count != 0)
            {
                Rig.AposeLSExits = true;
                Rig.AposeLSTrans = new Vec3[Rig.BoneCount];
                Rig.AposeLSRot   = new Quat[Rig.BoneCount];
                Rig.AposeLSScale = new Vec3[Rig.BoneCount];

                for (int i = 0; i < Rig.BoneCount; i++)
                {
                    float x = (cr2w.Chunks[0].Data as animRig).APoseLS[i].Translation.X.Value;
                    float y = (cr2w.Chunks[0].Data as animRig).APoseLS[i].Translation.Y.Value;
                    float z = (cr2w.Chunks[0].Data as animRig).APoseLS[i].Translation.Z.Value;
                    Rig.AposeLSTrans[i] = new Vec3(x, z, -y);
                    float I = (cr2w.Chunks[0].Data as animRig).APoseLS[i].Rotation.I.Value;
                    float J = (cr2w.Chunks[0].Data as animRig).APoseLS[i].Rotation.J.Value;
                    float K = (cr2w.Chunks[0].Data as animRig).APoseLS[i].Rotation.K.Value;
                    float R = (cr2w.Chunks[0].Data as animRig).APoseLS[i].Rotation.R.Value;
                    Rig.AposeLSRot[i] = new Quat(I, K, -J, R);
                    float t = (cr2w.Chunks[0].Data as animRig).APoseLS[i].Scale.X.Value;
                    float u = (cr2w.Chunks[0].Data as animRig).APoseLS[i].Scale.Y.Value;
                    float v = (cr2w.Chunks[0].Data as animRig).APoseLS[i].Scale.Z.Value;
                    Rig.AposeLSScale[i] = new Vec3(t, v, u);
                }
            }
            return(Rig);
        }
Ejemplo n.º 13
0
        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);
        }
Ejemplo n.º 14
0
        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);
        }
Ejemplo n.º 15
0
        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);
                }
            }
        }
Ejemplo n.º 16
0
        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);
        }
Ejemplo n.º 17
0
        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);
        }
Ejemplo n.º 18
0
        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);
        }
Ejemplo n.º 19
0
        public RawArmature ProcessRig(Stream fs)
        {
            BinaryReader br = new BinaryReader(fs);

            var cr2w = _modTools.TryReadRED4File(fs);

            if (cr2w == null || !cr2w.Chunks.Select(_ => _.Data).OfType <animRig>().Any())
            {
                return(new RawArmature());
            }
            RawArmature Rig = new RawArmature();

            Rig.Names     = GetboneNames(cr2w);
            Rig.BoneCount = Rig.Names.Length;

            var animrig = cr2w.Chunks.Select(_ => _.Data).OfType <animRig>().First();

            Rig.Parent = GetboneParents(animrig);

            Rig.LocalPosn = new Vec3[Rig.BoneCount];

            for (int i = 0; i < Rig.BoneCount; i++)
            {
                Vec3 v = new Vec3(animrig.Unk2[i][0].X.Value, animrig.Unk2[i][0].Y.Value, animrig.Unk2[i][0].Z.Value);
                Rig.LocalPosn[i] = new Vec3(v.X, v.Z, -v.Y);
            }

            Rig.LocalRot = new Quat[Rig.BoneCount];

            for (int i = 0; i < Rig.BoneCount; i++)
            {
                Quat q = new Quat(animrig.Unk2[i][1].X.Value, animrig.Unk2[i][1].Y.Value, animrig.Unk2[i][1].Z.Value, animrig.Unk2[i][1].W.Value);
                Rig.LocalRot[i] = new Quat(q.X, q.Z, -q.Y, q.W);
            }

            Rig.LocalScale = new Vec3[Rig.BoneCount];
            for (int i = 0; i < Rig.BoneCount; i++)
            {
                Vec3 v = new Vec3(animrig.Unk2[i][2].X.Value, animrig.Unk2[i][2].Y.Value, animrig.Unk2[i][2].Z.Value);
                Rig.LocalScale[i] = new Vec3(v.X, v.Y, v.Z);
            }

            // if AposeWorld/AposeMS Exists then..... this can be done better i guess...
            if ((cr2w.Chunks[0].Data as animRig).APoseMS.Count != 0)
            {
                Rig.AposeMSExits = true;
                Rig.AposeMSTrans = new Vec3[Rig.BoneCount];
                Rig.AposeMSRot   = new Quat[Rig.BoneCount];
                Rig.AposeMSScale = new Vec3[Rig.BoneCount];

                for (int i = 0; i < Rig.BoneCount; i++)
                {
                    float x = (cr2w.Chunks[0].Data as animRig).APoseMS[i].Translation.X.Value;
                    float y = (cr2w.Chunks[0].Data as animRig).APoseMS[i].Translation.Y.Value;
                    float z = (cr2w.Chunks[0].Data as animRig).APoseMS[i].Translation.Z.Value;
                    Rig.AposeMSTrans[i] = new Vec3(x, z, -y);
                    float I = (cr2w.Chunks[0].Data as animRig).APoseMS[i].Rotation.I.Value;
                    float J = (cr2w.Chunks[0].Data as animRig).APoseMS[i].Rotation.J.Value;
                    float K = (cr2w.Chunks[0].Data as animRig).APoseMS[i].Rotation.K.Value;
                    float R = (cr2w.Chunks[0].Data as animRig).APoseMS[i].Rotation.R.Value;
                    Rig.AposeMSRot[i] = new Quat(I, K, -J, R);
                    float t = (cr2w.Chunks[0].Data as animRig).APoseMS[i].Scale.X.Value;
                    float u = (cr2w.Chunks[0].Data as animRig).APoseMS[i].Scale.Y.Value;
                    float v = (cr2w.Chunks[0].Data as animRig).APoseMS[i].Scale.Z.Value;
                    Rig.AposeMSScale[i] = new Vec3(t, v, u);
                }
            }

            // not sure how APose works or how the matrix multiplication will be, maybe its a recursive mul
            if ((cr2w.Chunks[0].Data as animRig).APoseLS.Count != 0)
            {
                Rig.AposeLSExits = true;
                Rig.AposeLSTrans = new Vec3[Rig.BoneCount];
                Rig.AposeLSRot   = new Quat[Rig.BoneCount];
                Rig.AposeLSScale = new Vec3[Rig.BoneCount];

                for (int i = 0; i < Rig.BoneCount; i++)
                {
                    float x = (cr2w.Chunks[0].Data as animRig).APoseLS[i].Translation.X.Value;
                    float y = (cr2w.Chunks[0].Data as animRig).APoseLS[i].Translation.Y.Value;
                    float z = (cr2w.Chunks[0].Data as animRig).APoseLS[i].Translation.Z.Value;
                    Rig.AposeLSTrans[i] = new Vec3(x, z, -y);
                    float I = (cr2w.Chunks[0].Data as animRig).APoseLS[i].Rotation.I.Value;
                    float J = (cr2w.Chunks[0].Data as animRig).APoseLS[i].Rotation.J.Value;
                    float K = (cr2w.Chunks[0].Data as animRig).APoseLS[i].Rotation.K.Value;
                    float R = (cr2w.Chunks[0].Data as animRig).APoseLS[i].Rotation.R.Value;
                    Rig.AposeLSRot[i] = new Quat(I, K, -J, R);
                    float t = (cr2w.Chunks[0].Data as animRig).APoseLS[i].Scale.X.Value;
                    float u = (cr2w.Chunks[0].Data as animRig).APoseLS[i].Scale.Y.Value;
                    float v = (cr2w.Chunks[0].Data as animRig).APoseLS[i].Scale.Z.Value;
                    Rig.AposeLSScale[i] = new Vec3(t, v, u);
                }
            }
            string[] baseTendencyBoneNames = new string[] { "Root", "Hips", "Spine", "LeftUpLeg", "RightUpLeg", "Spine1", "LeftLeg", "RightLeg", "Spine2", "LeftFoot", "RightFoot", "Spine3",
                                                            "LeftShoulder", "RightShoulder", "Neck", "LeftArm", "RightArm", "Neck1", "LeftForeArm", "RightForeArm", "Head" };
            Rig.baseTendencyCount = 0;
            for (int i = 0; i < baseTendencyBoneNames.Length; i++)
            {
                if (Rig.Names.Contains(baseTendencyBoneNames[i]))
                {
                    Rig.baseTendencyCount++;
                }
            }
            return(Rig);
        }
Ejemplo n.º 20
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);
        }