Example #1
0
        public void Parse(ICLIFlags toolFlags)
        {
            var flags     = toolFlags as ExtractFlags;
            var testGuids = flags?.Positionals.Skip(3).Select(x => uint.Parse(x, System.Globalization.NumberStyles.HexNumber));

            foreach (var guid in Program.TrackedFiles[0xC])
            {
                if (!(testGuids ?? throw new InvalidDataException()).Contains(teResourceGUID.Index(guid)))
                {
                    continue;
                }
                using (Stream file = IO.OpenFile(guid))
                    using (BinaryReader reader = new BinaryReader(file)) {
                        teChunkedData    chunk    = new teChunkedData(reader);
                        teModelChunk_STU stuChunk = chunk.GetChunk <teModelChunk_STU>();

                        var hitboxes = stuChunk.StructuredData.m_CB4D298D;
                        var complex  = hitboxes.Select(x => x.m_B7C8314A).OfType <STU_B3800E70>().First();
                        var lines    = new List <string> {
                            "ply",
                            "format ascii 1.0",
                            $"element vertex {complex.m_88FCECD7.Length}",
                            "property float x",
                            "property float y",
                            "property float z",
                            "end_header"
                        };
                        lines.AddRange(complex.m_88FCECD7.Select(x => $"{x.X} {x.Y} {x.Z}")); // vertex

                        File.WriteAllText(@"F:\Test.ply", string.Join("\n", lines));
                    }
            }
        }
Example #2
0
        public void Write(Stream stream)
        {
            teModelChunk_RenderMesh renderMesh = _data.GetChunk <teModelChunk_RenderMesh>();
            teModelChunk_Model      model      = _data.GetChunk <teModelChunk_Model>();
            teModelChunk_Skeleton   skeleton   = _data.GetChunk <teModelChunk_Skeleton>();
            teModelChunk_Cloth      cloth      = _data.GetChunk <teModelChunk_Cloth>();
            teModelChunk_STU        stu        = _data.GetChunk <teModelChunk_STU>();

            using (BinaryWriter writer = new BinaryWriter(stream)) {
                writer.Write((ushort)1);
                writer.Write((ushort)6);
                if (ModelLookFileName == null)     // mat ref
                {
                    writer.Write((byte)0);
                }
                else
                {
                    writer.Write(ModelLookFileName);
                }
                if (Name == null)     // model name
                {
                    writer.Write((byte)0);
                }
                else
                {
                    writer.Write(Name);
                }

                short[] hierarchy = null;
                Dictionary <int, teModelChunk_Cloth.ClothNode> clothNodeMap = null;
                if (skeleton != null)
                {
                    if (cloth != null)
                    {
                        hierarchy = cloth.CreateFakeHierarchy(skeleton, out clothNodeMap);
                    }
                    else
                    {
                        hierarchy = skeleton.Hierarchy;
                    }
                    writer.Write(skeleton.Header.BonesAbs);
                }
                else
                {
                    writer.Write((ushort)0);
                }

                if (renderMesh == null)
                {
                    writer.Write(0u);
                    writer.Write(0);
                    return;
                }
                teModelChunk_RenderMesh.Submesh[] submeshes = renderMesh.Submeshes.Where(x => x.Descriptor.LOD == TargetLod || x.Descriptor.LOD == -1).ToArray();

                writer.Write((uint)submeshes.Length);

                if (stu?.StructuredData.m_hardPoints != null)
                {
                    writer.Write(stu.StructuredData.m_hardPoints.Length);
                }
                else
                {
                    writer.Write(0);  // hardpoints
                }

                if (skeleton != null)
                {
                    for (int i = 0; i < skeleton.Header.BonesAbs; ++i)
                    {
                        writer.Write(GetBoneName(skeleton.IDs[i]));
                        short parent = hierarchy[i];
                        if (parent == -1)
                        {
                            parent = (short)i;
                        }
                        writer.Write(parent);

                        skeleton.GetWorldSpace(i, out teVec3 scale, out teQuat rotation, out teVec3 translation);
                        writer.Write(translation);
                        writer.Write(scale);
                        writer.Write(rotation);
                    }
                }

                int submeshIdx = 0;
                foreach (teModelChunk_RenderMesh.Submesh submesh in submeshes)
                {
                    writer.Write($"Submesh_{submeshIdx}.{model.Materials[submesh.Descriptor.Material]:X16}");
                    writer.Write(model.Materials[submesh.Descriptor.Material]);
                    writer.Write(submesh.UVCount);

                    writer.Write(submesh.Vertices.Length);
                    writer.Write(submesh.Indices.Length / 3);

                    for (int j = 0; j < submesh.Vertices.Length; j++)
                    {
                        writer.Write(submesh.Vertices[j]);
                        writer.Write(-submesh.Normals[j].X);
                        writer.Write(-submesh.Normals[j].Y);
                        writer.Write(-submesh.Normals[j].Z);

                        foreach (teVec2 uv in submesh.UV[j])
                        {
                            writer.Write(uv);
                        }

                        if (skeleton != null && submesh.BoneIndices[j] != null)
                        {
                            writer.Write((byte)4);
                            writer.Write(skeleton.Lookup[submesh.BoneIndices[j][0]]);
                            writer.Write(skeleton.Lookup[submesh.BoneIndices[j][1]]);
                            writer.Write(skeleton.Lookup[submesh.BoneIndices[j][2]]);
                            writer.Write(skeleton.Lookup[submesh.BoneIndices[j][3]]);
                            writer.Write(submesh.BoneWeights[j][0]);
                            writer.Write(submesh.BoneWeights[j][1]);
                            writer.Write(submesh.BoneWeights[j][2]);
                            writer.Write(submesh.BoneWeights[j][3]);
                        }
                        else
                        {
                            writer.Write((byte)0);
                        }

                        writer.Write(submesh.Color1.ElementAtOrDefault(j));
                        writer.Write(submesh.Color2.ElementAtOrDefault(j));
                    }

                    for (int j = 0; j < submesh.Descriptor.IndicesToDraw; j += 3)
                    {
                        writer.Write((byte)3);
                        writer.Write((int)submesh.Indices[j]);
                        writer.Write((int)submesh.Indices[j + 1]);
                        writer.Write((int)submesh.Indices[j + 2]);
                    }

                    submeshIdx++;
                }


                if (stu?.StructuredData.m_hardPoints != null)
                {
                    foreach (STUModelHardpoint hardPoint in stu.StructuredData.m_hardPoints)
                    {
                        writer.Write(IdToString("hardpoint", teResourceGUID.Index(hardPoint.m_EDF0511C)));

                        Matrix parentMat = Matrix.Identity;
                        if (hardPoint.m_FF592924 != 0 && skeleton != null)
                        {
                            int?boneIdx         = null;
                            var hardPointBoneID = teResourceGUID.Index(hardPoint.m_FF592924);
                            for (int i = 0; i < skeleton.IDs.Length; i++)
                            {
                                var currBoneID = skeleton.IDs[i];
                                if (currBoneID == hardPointBoneID)
                                {
                                    boneIdx = i;
                                    break;
                                }
                            }

                            if (boneIdx == null)
                            {
                                parentMat = Matrix.Identity;
                                Logger.Debug("OverwatchModel",
                                             $"Hardpoint {teResourceGUID.AsString(hardPoint.m_EDF0511C)} is attached to bone {teResourceGUID.AsString(hardPoint.m_FF592924)} which doesn't exist on model {teResourceGUID.AsString(GUID)}");
                            }
                            else
                            {
                                parentMat = skeleton.GetWorldSpace(boneIdx.Value);
                            }
                        }

                        Matrix hardPointMat = Matrix.RotationQuaternion(hardPoint.m_rotation) *
                                              Matrix.Translation(hardPoint.m_position);

                        hardPointMat = hardPointMat * parentMat;
                        hardPointMat.Decompose(out Vector3 _, out Quaternion rot, out Vector3 pos);

                        writer.Write(pos);
                        writer.Write(rot);
                    }

                    foreach (STUModelHardpoint modelHardpoint in stu.StructuredData.m_hardPoints)
                    {
                        writer.Write(IdToString("bone", teResourceGUID.Index(modelHardpoint.m_FF592924)));
                    }
                }

                // ext 1.3: old cloth
                writer.Write(0);

                // ext 1.4: embedded refpose
                if (skeleton != null)
                {
                    for (int i = 0; i < skeleton.Header.BonesAbs; ++i)
                    {
                        writer.Write(IdToString("bone", skeleton.IDs[i]));
                        short parent = hierarchy[i];
                        writer.Write(parent);

                        GetRefPoseTransform(i, hierarchy, skeleton, clothNodeMap, out teVec3 scale, out teQuat quat,
                                            out teVec3 translation);

                        teVec3 rot = quat.ToEulerAngles();
                        writer.Write(translation);
                        writer.Write(scale);
                        writer.Write(rot);
                    }
                }

                writer.Write(teResourceGUID.Index(GUID));
            }
        }