コード例 #1
0
        public bool Create(SKNFile file, Logger logger)
        {
            // This function converts the handedness of the DirectX style input data
            // into the handedness OpenGL expects.
            // So, vector inputs have their Z value negated and quaternion inputs have their
            // Z and W values negated.

            List <float> vertexPositions          = new List <float>();
            List <float> vertexNormals            = new List <float>();
            List <float> vertexTextureCoordinates = new List <float>();

            for (int i = 0; i < file.numVertices; ++i)
            {
                vertexPositions.Add(file.vertices[i].position[0]);
                vertexPositions.Add(file.vertices[i].position[1]);
                vertexPositions.Add(-file.vertices[i].position[2]);

                vertexNormals.Add(file.vertices[i].normal[0]);
                vertexNormals.Add(file.vertices[i].normal[1]);
                vertexNormals.Add(-file.vertices[i].normal[2]);

                vertexTextureCoordinates.Add(file.vertices[i].texCoords[0]);
                vertexTextureCoordinates.Add(file.vertices[i].texCoords[1]);
            }

            List <uint> iData = new List <uint>();

            for (int i = 0; i < numIndices; ++i)
            {
                iData.Add((uint)file.indices[i]);
            }

            return(Create(vertexPositions, vertexNormals, vertexTextureCoordinates, iData, logger));
        }
コード例 #2
0
        /// <summary>
        /// Converts <paramref name="skn"/> to a list of <see cref="MeshGeometry3D"/>
        /// </summary>
        /// <param name="skn">The <see cref="SKNFile"/> which should get converted to a <c>Tuple{string, MeshGeometry3D}(submeshName, submeshData)</c></param>
        /// <returns>A collection of converted <see cref="SKNSubmesh"/></returns>
        /// <remarks>Normals do not get converted</remarks>
        public static IEnumerable <Tuple <string, MeshGeometry3D> > ConvertSKN(SKNFile skn)
        {
            foreach (SKNSubmesh submesh in skn.Submeshes)
            {
                MeshGeometry3D mesh = new MeshGeometry3D();

                Int32Collection    indices  = new Int32Collection(submesh.Indices.Select(x => (int)x));
                Point3DCollection  vertices = new Point3DCollection();
                Vector3DCollection normals  = new Vector3DCollection();
                PointCollection    uvs      = new PointCollection();
                for (int i = 0; i < submesh.Vertices.Count; i++)
                {
                    SKNVertex vertex = submesh.Vertices[i];
                    vertices.Add(new Point3D(vertex.Position.X, vertex.Position.Y, vertex.Position.Z));
                    normals.Add(new Vector3D(vertex.Normal.X, vertex.Normal.Y, vertex.Normal.Z));
                    uvs.Add(new Point(vertex.UV.X, vertex.UV.Y));
                }

                mesh.TextureCoordinates = uvs;
                mesh.Positions          = vertices;
                mesh.Normals            = normals;
                mesh.TriangleIndices    = indices;

                yield return(new Tuple <string, MeshGeometry3D>(submesh.Name, mesh));
            }
        }
コード例 #3
0
        public static void Process(string fileLocation, SKNFile skn)
        {
            string exportDirectory = string.Format(@"{0}\Uvee_{1}", Path.GetDirectoryName(fileLocation), Path.GetFileNameWithoutExtension(fileLocation));

            Directory.CreateDirectory(exportDirectory);

            foreach (SKNSubmesh submesh in skn.Submeshes)
            {
                Image         image   = CreateImage();
                List <ushort> indices = submesh.GetNormalizedIndices();

                //Loop through all submesh faces and draw the lines for them using vertex UV
                for (int i = 0; i < indices.Count;)
                {
                    SKNVertex vertex1 = submesh.Vertices[indices[i++]];
                    SKNVertex vertex2 = submesh.Vertices[indices[i++]];
                    SKNVertex vertex3 = submesh.Vertices[indices[i++]];

                    PointF[] points = new PointF[]
                    {
                        new PointF(1024 * vertex1.UV.X, 1024 * vertex1.UV.Y),
                        new PointF(1024 * vertex2.UV.X, 1024 * vertex2.UV.Y),
                        new PointF(1024 * vertex3.UV.X, 1024 * vertex3.UV.Y),
                        new PointF(1024 * vertex1.UV.X, 1024 * vertex1.UV.Y) //4th point to close the edge loop
                    };

                    DrawLines(image, points);
                }

                string submeshLocation = string.Format(@"{0}\{1}.png", exportDirectory, submesh.Name);
                image.SaveAsPng(File.Create(submeshLocation));
            }
        }
コード例 #4
0
ファイル: SCOConverter.cs プロジェクト: sahlie1985/Legends
        /// <summary>
        /// Converts <paramref name="skn"/> to a <c>Tuple{SCOFile, WGTFile}</c>
        /// </summary>
        /// <param name="skn">The <see cref="SKNFile"/> to convert to a <c>Tuple{SCOFile, WGTFile}</c></param>
        /// <returns>A <c>Tuple{SCOFile, WGTFile}</c> converted from <paramref name="skn"/></returns>
        public static Tuple <SCOFile, WGTFile> ConvertToLegacy(SKNFile skn)
        {
            List <Vector3> vertices = new List <Vector3>();
            Dictionary <string, List <SCOFace> > materials = new Dictionary <string, List <SCOFace> >();
            List <Vector4Byte> boneIndices = new List <Vector4Byte>();
            List <Vector4>     weights     = new List <Vector4>();

            foreach (SKNSubmesh submesh in skn.Submeshes)
            {
                List <SCOFace> faces = new List <SCOFace>();
                for (int i = 0; i < submesh.Indices.Count; i += 3)
                {
                    faces.Add(new SCOFace(new uint[] { submesh.Indices[i], submesh.Indices[i + 1], submesh.Indices[i + 2], }, submesh.Name,
                                          new Vector2[]
                    {
                        submesh.Vertices[submesh.Indices[i]].UV,
                        submesh.Vertices[submesh.Indices[i + 1]].UV,
                        submesh.Vertices[submesh.Indices[i + 2]].UV,
                    }));
                }
                materials.Add(submesh.Name, faces);

                foreach (SKNVertex vertex in submesh.Vertices)
                {
                    vertices.Add(vertex.Position);
                    weights.Add(vertex.Weights);
                    boneIndices.Add(vertex.BoneIndices);
                }
            }
            return(new Tuple <SCOFile, WGTFile>(new SCOFile(vertices, materials), new WGTFile(weights, boneIndices)));
        }
コード例 #5
0
        //public static OBJFile VisualiseNVRNodes(NVRFile Nvr)
        //{
        //    List<UInt16> Indices = new List<UInt16>();
        //    List<UInt16> BaseIndices = new List<UInt16>()
        //    {
        //        0, 1, 2,
        //        0, 3, 2,

        //        4, 5, 6,
        //        4, 7, 6,

        //        6, 5, 1,
        //        6, 2, 1,

        //        0, 4, 7,
        //        0, 3, 7,

        //        2, 6, 7,
        //        2, 3, 7,

        //        0, 1, 5,
        //        0, 4, 5
        //    };
        //    List<Vector3> Vertices = new List<Vector3>();
        //    List<NVRNode> Nodes = Nvr.GetNodes();
        //    foreach (NVRNode Node in Nodes)
        //    {
        //        /* 0 Vector3 minLeftUp = Node.BoundingBox.Min;
        //           1 Vector3 minRightUp = new Vector3(Node.BoundingBox.Min.X, Node.BoundingBox.Min.Y, Node.BoundingBox.Max.Z);
        //           2 Vector3 minLeftDown = new Vector3(Node.BoundingBox.Max.X, Node.BoundingBox.Min.Y, Node.BoundingBox.Min.Z);
        //           3 Vector3 minRightDown = new Vector3(Node.BoundingBox.Max.X, Node.BoundingBox.Min.Y, Node.BoundingBox.Max.Z);

        //           6 Vector3 maxRightDown = Node.BoundingBox.Max;
        //           7 Vector3 maxLeftDown = new Vector3(Node.BoundingBox.Max.X, Node.BoundingBox.Max.Y, Node.BoundingBox.Min.Z);
        //           4 Vector3 maaxLeftUp = new Vector3(Node.BoundingBox.Min.X, Node.BoundingBox.Max.Y, Node.BoundingBox.Min.Z);
        //           5 Vector3 maxRightUp = new Vector3(Node.BoundingBox.Max.X, Node.BoundingBox.Min.Y, Node.BoundingBox.Max.Z);*/

        //        Vertices.AddRange(new Vector3[]
        //        {
        //            Node.BoundingBox.Min,
        //            new Vector3(Node.BoundingBox.Min.X, Node.BoundingBox.Min.Y, Node.BoundingBox.Max.Z),
        //            new Vector3(Node.BoundingBox.Max.X, Node.BoundingBox.Min.Y, Node.BoundingBox.Min.Z),
        //            new Vector3(Node.BoundingBox.Max.X, Node.BoundingBox.Min.Y, Node.BoundingBox.Max.Z),
        //            new Vector3(Node.BoundingBox.Min.X, Node.BoundingBox.Max.Y, Node.BoundingBox.Min.Z),
        //            new Vector3(Node.BoundingBox.Max.X, Node.BoundingBox.Min.Y, Node.BoundingBox.Max.Z),
        //            Node.BoundingBox.Max,
        //            new Vector3(Node.BoundingBox.Max.X, Node.BoundingBox.Max.Y, Node.BoundingBox.Min.Z),
        //    });
        //    }
        //    for (int i = 0; i * 8 < Vertices.Count; i++)
        //    {
        //        Indices.AddRange(BaseIndices);
        //        for (int j = 0; j < BaseIndices.Count; j++)
        //        {
        //            BaseIndices[j] += 8;
        //        }
        //    }
        //    return new OBJFile(Vertices, Indices);
        //}

        public static OBJFile ConvertSKN(SKNFile Model)
        {
            List <Vector3> Vertices = new List <Vector3>();
            List <Vector2> UV       = new List <Vector2>();
            List <Vector3> Normals  = new List <Vector3>();

            foreach (SKNVertex Vertex in Model.Vertices)
            {
                Vertices.Add(Vertex.Position);
                UV.Add(Vertex.UV);
                Normals.Add(Vertex.Normal);
            }

            return(new OBJFile(Vertices, UV, Normals, Model.Indices));
        }
コード例 #6
0
        private bool CreateStaticModel(LOLModel model, Logger logger)
        {
            bool result = true;

            logger.Event("Creating static model.");

            SKNFile file = new SKNFile();

            if (result == true)
            {
                // Model is stored in a RAF.
                result = SKNReader.Read(model.skn, ref file, logger);
            }

            staticModel = new GLStaticModel();
            if (result == true)
            {
                result = staticModel.Create(file, logger);
            }

            //
            // Create Model Texture.
            //

            if (result == true)
            {
                // Texture stored in RAF file.
                result = CreateTexture(model.texture, TextureTarget.Texture2D,
                                       GLTexture.SupportedImageEncodings.DDS, logger);

                // Store it in our new model file.
                if (result == true)
                {
                    String name = model.texture.FileName;
                    int    pos  = name.LastIndexOf("/");
                    name = name.Substring(pos + 1);

                    staticModel.TextureName = name;
                }
            }

            if (result == false)
            {
                logger.Error("Failed to create static model.");
            }

            return(result);
        }
コード例 #7
0
        public static Tuple <SCOFile, WGTFile> ConvertToLegacy(SKNFile SKN)
        {
            List <Vector3>     Vertices    = new List <Vector3>();
            List <Vector2>     UV          = new List <Vector2>();
            List <Vector4Byte> BoneIndices = new List <Vector4Byte>();
            List <Vector4>     Weights     = new List <Vector4>();

            foreach (SKNVertex Vertex in SKN.Vertices)
            {
                Vertices.Add(Vertex.Position);
                UV.Add(Vertex.UV);
                Weights.Add(Vertex.Weights);
                BoneIndices.Add(Vertex.BoneIndices);
            }
            return(new Tuple <SCOFile, WGTFile>(new SCOFile(SKN.Indices, Vertices, UV), new WGTFile(Weights, BoneIndices)));
        }
コード例 #8
0
        public override void writer(MFileObject file, string optionsString, FileAccessMode mode)
        {
            if (mode == FileAccessMode.kExportActiveAccessMode)
            {
                string sknPath = file.expandedFullName;
                string sklPath = Path.ChangeExtension(sknPath, ".skl");

                SKLFile skl = new SKLFile(true);
                SKNFile skn = new SKNFile(skl);

                skl.Write(sklPath);
                skn.Write(sknPath);
            }
            else
            {
                MGlobal.displayError("SKNExporter - Wrong File Access Mode: " + mode);
            }
        }
コード例 #9
0
        /// <summary>
        /// Converts the Submeshes of the specified <see cref="SKNFile"/> into a List of <see cref="OBJFile"/>
        /// </summary>
        /// <param name="model"><see cref="SKNFile"/> to convert</param>
        public static IEnumerable <Tuple <string, OBJFile> > ConvertSKNModels(SKNFile model)
        {
            foreach (SKNSubmesh submesh in model.Submeshes)
            {
                List <uint>    indices  = new List <uint>();
                List <Vector3> vertices = new List <Vector3>();
                List <Vector2> uv       = new List <Vector2>();
                List <Vector3> normals  = new List <Vector3>();
                indices.AddRange(submesh.Indices.Select(i => (uint)i));
                foreach (SKNVertex vertex in submesh.Vertices)
                {
                    vertices.Add(vertex.Position);
                    uv.Add(vertex.UV);
                    normals.Add(vertex.Normal);
                }

                yield return(new Tuple <string, OBJFile>(submesh.Name, new OBJFile(vertices, indices, uv, normals)));
            }
        }
コード例 #10
0
        //public static OBJFile VisualiseNVRNodes(NVRFile Nvr)
        //{
        //    List<UInt16> Indices = new List<UInt16>();
        //    List<UInt16> BaseIndices = new List<UInt16>()
        //    {
        //        0, 1, 2,
        //        0, 3, 2,

        //        4, 5, 6,
        //        4, 7, 6,

        //        6, 5, 1,
        //        6, 2, 1,

        //        0, 4, 7,
        //        0, 3, 7,

        //        2, 6, 7,
        //        2, 3, 7,

        //        0, 1, 5,
        //        0, 4, 5
        //    };
        //    List<Vector3> Vertices = new List<Vector3>();
        //    List<NVRNode> Nodes = Nvr.GetNodes();
        //    foreach (NVRNode Node in Nodes)
        //    {
        //        /* 0 Vector3 minLeftUp = Node.BoundingBox.Min;
        //           1 Vector3 minRightUp = new Vector3(Node.BoundingBox.Min.X, Node.BoundingBox.Min.Y, Node.BoundingBox.Max.Z);
        //           2 Vector3 minLeftDown = new Vector3(Node.BoundingBox.Max.X, Node.BoundingBox.Min.Y, Node.BoundingBox.Min.Z);
        //           3 Vector3 minRightDown = new Vector3(Node.BoundingBox.Max.X, Node.BoundingBox.Min.Y, Node.BoundingBox.Max.Z);

        //           6 Vector3 maxRightDown = Node.BoundingBox.Max;
        //           7 Vector3 maxLeftDown = new Vector3(Node.BoundingBox.Max.X, Node.BoundingBox.Max.Y, Node.BoundingBox.Min.Z);
        //           4 Vector3 maaxLeftUp = new Vector3(Node.BoundingBox.Min.X, Node.BoundingBox.Max.Y, Node.BoundingBox.Min.Z);
        //           5 Vector3 maxRightUp = new Vector3(Node.BoundingBox.Max.X, Node.BoundingBox.Min.Y, Node.BoundingBox.Max.Z);*/

        //        Vertices.AddRange(new Vector3[]
        //        {
        //            Node.BoundingBox.Min,
        //            new Vector3(Node.BoundingBox.Min.X, Node.BoundingBox.Min.Y, Node.BoundingBox.Max.Z),
        //            new Vector3(Node.BoundingBox.Max.X, Node.BoundingBox.Min.Y, Node.BoundingBox.Min.Z),
        //            new Vector3(Node.BoundingBox.Max.X, Node.BoundingBox.Min.Y, Node.BoundingBox.Max.Z),
        //            new Vector3(Node.BoundingBox.Min.X, Node.BoundingBox.Max.Y, Node.BoundingBox.Min.Z),
        //            new Vector3(Node.BoundingBox.Max.X, Node.BoundingBox.Min.Y, Node.BoundingBox.Max.Z),
        //            Node.BoundingBox.Max,
        //            new Vector3(Node.BoundingBox.Max.X, Node.BoundingBox.Max.Y, Node.BoundingBox.Min.Z),
        //    });
        //    }
        //    for (int i = 0; i * 8 < Vertices.Count; i++)
        //    {
        //        Indices.AddRange(BaseIndices);
        //        for (int j = 0; j < BaseIndices.Count; j++)
        //        {
        //            BaseIndices[j] += 8;
        //        }
        //    }
        //    return new OBJFile(Vertices, Indices);
        //}

        /// <summary>
        /// Converts <paramref name="model"/> to an <see cref="OBJFile"/>
        /// </summary>
        /// <param name="model">The <see cref="SKNFile"/> to convert to a <see cref="OBJFile"/></param>
        /// <returns>An <see cref="OBJFile"/> converted from <paramref name="model"/></returns>
        public static OBJFile ConvertSKN(SKNFile model)
        {
            List <uint>    indices  = new List <uint>();
            List <Vector3> vertices = new List <Vector3>();
            List <Vector2> uv       = new List <Vector2>();
            List <Vector3> normals  = new List <Vector3>();

            foreach (SKNSubmesh submesh in model.Submeshes)
            {
                indices.AddRange(submesh.Indices.Cast <uint>());
                foreach (SKNVertex vertex in submesh.Vertices)
                {
                    vertices.Add(vertex.Position);
                    uv.Add(vertex.UV);
                    normals.Add(vertex.Normal);
                }
            }


            return(new OBJFile(vertices, indices, uv, normals));
        }
コード例 #11
0
        public override void reader(MFileObject file, string optionsString, FileAccessMode mode)
        {
            if (mode == FileAccessMode.kImportAccessMode)
            {
                string pathWithoutExtension = file.expandedFullName.Substring(0, file.expandedFullName.LastIndexOf('.'));
                string name = Path.GetFileNameWithoutExtension(file.expandedFullName).Replace('.', '_');

                SKNFile skn = new SKNFile(file.expandedFullName);
                SKLFile skl = new SKLFile(pathWithoutExtension + ".skl");

                MGlobal.displayInfo("SKNImporter:reader - SKN Vertex Count: " + skn.Vertices.Count);
                MGlobal.displayInfo("SKNImporter:reader - SKN Index Count: " + skn.Indices.Count);
                MGlobal.displayInfo("SKNImporter:reader - SKN Submesh Count: " + skn.Submeshes.Count);

                skl.Load();
                skn.Load(name, skl);
            }
            else
            {
                throw new ArgumentException("SKNImporter:reader - Invalid File Access Mode: " + mode, "mode");
            }
        }
コード例 #12
0
        /// <summary>
        /// Loads data from SKN and SKL files into OpenGL.
        /// </summary>
        /// <param name="skn">The .skn data.</param>
        /// <param name="skl">The .skl data.</param>
        /// <returns></returns>
        public bool Create(SKNFile skn, SKLFile skl, Dictionary <String, ANMFile> anms, Logger logger)
        {
            bool result = true;

            // This function converts the handedness of the DirectX style input data
            // into the handedness OpenGL expects.
            // So, vector inputs have their Z value negated and quaternion inputs have their
            // Z and W values negated.

            // Vertex Data
            List <float> vertexPositions          = new List <float>();
            List <float> vertexNormals            = new List <float>();
            List <float> vertexTextureCoordinates = new List <float>();
            List <float> vertexBoneIndices        = new List <float>();
            List <float> vertexBoneWeights        = new List <float>();
            List <uint>  indices = new List <uint>();

            // Animation data.
            List <OpenTK.Quaternion> boneOrientations = new List <OpenTK.Quaternion>();
            List <OpenTK.Vector3>    bonePositions    = new List <OpenTK.Vector3>();
            List <float>             boneScales       = new List <float>();
            List <int>    boneParents = new List <int>();
            List <String> boneNames   = new List <String>();

            // Bones are not always in order between the ANM and SKL files.
            Dictionary <String, int> boneNameToID = new Dictionary <String, int>();
            Dictionary <int, String> boneIDToName = new Dictionary <int, String>();

            for (int i = 0; i < skn.numVertices; ++i)
            {
                // Position Information
                vertexPositions.Add(skn.vertices[i].position[0]);
                vertexPositions.Add(skn.vertices[i].position[1]);
                vertexPositions.Add(-skn.vertices[i].position[2]);

                // Normal Information
                vertexNormals.Add(skn.vertices[i].normal[0]);
                vertexNormals.Add(skn.vertices[i].normal[1]);
                vertexNormals.Add(-skn.vertices[i].normal[2]);

                // Tex Coords Information
                vertexTextureCoordinates.Add(skn.vertices[i].texCoords[0]);
                vertexTextureCoordinates.Add(skn.vertices[i].texCoords[1]);

                // Bone Index Information
                for (int j = 0; j < SKNVertex.BONE_INDEX_SIZE; ++j)
                {
                    vertexBoneIndices.Add(skn.vertices[i].boneIndex[j]);
                }

                // Bone Weight Information
                vertexBoneWeights.Add(skn.vertices[i].weights[0]);
                vertexBoneWeights.Add(skn.vertices[i].weights[1]);
                vertexBoneWeights.Add(skn.vertices[i].weights[2]);
                vertexBoneWeights.Add(skn.vertices[i].weights[3]);
            }

            // Animation data
            for (int i = 0; i < skl.numBones; ++i)
            {
                Quaternion orientation = Quaternion.Identity;
                if (skl.version == 0)
                {
                    // Version 0 SKLs contain a quaternion.
                    orientation.X = skl.bones[i].orientation[0];
                    orientation.Y = skl.bones[i].orientation[1];
                    orientation.Z = -skl.bones[i].orientation[2];
                    orientation.W = -skl.bones[i].orientation[3];
                }
                else
                {
                    // Other SKLs contain a rotation matrix.

                    // Create a matrix from the orientation values.
                    Matrix4 transform = Matrix4.Identity;

                    transform.M11 = skl.bones[i].orientation[0];
                    transform.M21 = skl.bones[i].orientation[1];
                    transform.M31 = skl.bones[i].orientation[2];

                    transform.M12 = skl.bones[i].orientation[4];
                    transform.M22 = skl.bones[i].orientation[5];
                    transform.M32 = skl.bones[i].orientation[6];

                    transform.M13 = skl.bones[i].orientation[8];
                    transform.M23 = skl.bones[i].orientation[9];
                    transform.M33 = skl.bones[i].orientation[10];

                    // Convert the matrix to a quaternion.
                    orientation   = OpenTKExtras.Matrix4.CreateQuatFromMatrix(transform);
                    orientation.Z = -orientation.Z;
                    orientation.W = -orientation.W;
                }

                boneOrientations.Add(orientation);

                // Create a vector from the position values.
                Vector3 position = Vector3.Zero;
                position.X = skl.bones[i].position[0];
                position.Y = skl.bones[i].position[1];
                position.Z = -skl.bones[i].position[2];
                bonePositions.Add(position);

                boneNames.Add(skl.bones[i].name);
                boneNameToID[skl.bones[i].name] = i;
                boneIDToName[i] = skl.bones[i].name;

                boneScales.Add(skl.bones[i].scale);
                boneParents.Add(skl.bones[i].parentID);
            }

            //
            // Version 0 SKL files are similar to the animation files.
            // The bone positions and orientations are relative to their parent.
            // So, we need to compute their absolute location by hand.
            //
            if (skl.version == 0)
            {
                //
                // This algorithm is a little confusing since it's indexing identical data from
                // the SKL file and the local variable List<>s. The indexing scheme works because
                // the List<>s are created in the same order as the data in the SKL files.
                //
                for (int i = 0; i < skl.numBones; ++i)
                {
                    // Only update non root bones.
                    if (skl.bones[i].parentID != -1)
                    {
                        // Determine the parent bone.
                        int parentBoneID = skl.bones[i].parentID;

                        // Update orientation.
                        // Append quaternions for rotation transform B * A.
                        boneOrientations[i] = boneOrientations[parentBoneID] * boneOrientations[i];

                        Vector3 localPosition = Vector3.Zero;
                        localPosition.X = skl.bones[i].position[0];
                        localPosition.Y = skl.bones[i].position[1];
                        localPosition.Z = skl.bones[i].position[2];

                        // Update position.
                        bonePositions[i] = bonePositions[parentBoneID] + Vector3.Transform(localPosition, boneOrientations[parentBoneID]);
                    }
                }
            }

            // Depending on the version of the model, the look ups change.
            if (skl.version == 2 || skl.version == 0)
            {
                for (int i = 0; i < vertexBoneIndices.Count; ++i)
                {
                    // I don't know why things need remapped, but they do.

                    // Sanity
                    if (vertexBoneIndices[i] < skl.boneIDs.Count)
                    {
                        vertexBoneIndices[i] = skl.boneIDs[(int)vertexBoneIndices[i]];
                    }
                }
            }

            // Add the animations.
            foreach (var animation in anms)
            {
                if (animations.ContainsKey(animation.Key) == false)
                {
                    // Create the OpenGL animation wrapper.
                    GLAnimation glAnimation = new GLAnimation();

                    glAnimation.playbackFPS    = animation.Value.playbackFPS;
                    glAnimation.numberOfBones  = animation.Value.numberOfBones;
                    glAnimation.numberOfFrames = animation.Value.numberOfFrames;

                    // Convert ANMBone to GLBone.
                    foreach (ANMBone bone in animation.Value.bones)
                    {
                        GLBone glBone = new GLBone();

                        if (animation.Value.version == 4 && skl.boneIDMap.Count > 0)
                        {
                            // Version 4 ANM files contain a hash value to represent the bone ID/name.
                            // We need to use the map from the SKL file to match the ANM bone with the correct
                            // SKL bone.

                            if (skl.boneIDMap.ContainsKey(bone.id))
                            {
                                int sklID = (int)skl.boneIDMap[bone.id];
                                glBone.name = boneIDToName[sklID];
                            }
                        }
                        else
                        {
                            glBone.name = bone.name;
                        }

                        // Convert ANMFrame to Matrix4.
                        foreach (ANMFrame frame in bone.frames)
                        {
                            Matrix4 transform = Matrix4.Identity;

                            Quaternion quat = new Quaternion(frame.orientation[0], frame.orientation[1], -frame.orientation[2], -frame.orientation[3]);
                            transform = Matrix4.Rotate(quat);

                            transform.M41 = frame.position[0];
                            transform.M42 = frame.position[1];
                            transform.M43 = -frame.position[2];

                            glBone.frames.Add(transform);
                        }

                        glAnimation.bones.Add(glBone);
                    }

                    glAnimation.timePerFrame = 1.0f / (float)animation.Value.playbackFPS;

                    // Store the animation.
                    animations.Add(animation.Key, glAnimation);
                }
            }

            // Index Information
            for (int i = 0; i < skn.numIndices; ++i)
            {
                indices.Add((uint)skn.indices[i]);
            }
            this.numIndices = indices.Count;

            //
            // Compute the final animation transforms.
            //

            foreach (var animation in animations)
            {
                // This is sort of a mess.
                // We need to make sure "parent" bones are always updated before their "children".  The SKL file contains
                // bones ordered in this manner.  However, ANM files do not always do this.  So, we sort the bones in the ANM to match the ordering in
                // the SKL file.
                animation.Value.bones.Sort((a, b) =>
                {
                    if (boneNameToID.ContainsKey(a.name) && boneNameToID.ContainsKey(b.name))
                    {
                        return(boneNameToID[a.name].CompareTo(boneNameToID[b.name]));
                    }
                    else if (boneNameToID.ContainsKey(a.name) == false)
                    {
                        return(1);
                    }
                    else
                    {
                        return(-1);
                    }
                });
            }

            // Create the binding transform.  (The SKL initial transform.)
            GLAnimation bindingBones = new GLAnimation();

            for (int i = 0; i < boneOrientations.Count; ++i)
            {
                GLBone bone = new GLBone();

                bone.name   = boneNames[i];
                bone.parent = boneParents[i];

                bone.transform     = Matrix4.Rotate(boneOrientations[i]);
                bone.transform.M41 = bonePositions[i].X;
                bone.transform.M42 = bonePositions[i].Y;
                bone.transform.M43 = bonePositions[i].Z;

                bone.transform = Matrix4.Invert(bone.transform);

                bindingBones.bones.Add(bone);
            }

            // Convert animations into absolute space.
            foreach (var animation in animations)
            {
                foreach (var bone in animation.Value.bones)
                {
                    // Sanity.
                    if (boneNameToID.ContainsKey(bone.name))
                    {
                        int id = boneNameToID[bone.name];
                        bone.parent = bindingBones.bones[id].parent;

                        // For each frame...
                        for (int i = 0; i < bone.frames.Count; ++i)
                        {
                            Matrix4 parentTransform = Matrix4.Identity;
                            if (bone.parent >= 0)
                            {
                                if (bone.parent < animation.Value.bones.Count)
                                {
                                    GLBone parent = animation.Value.bones[bone.parent];
                                    parentTransform = parent.frames[i];
                                }
                            }
                            bone.frames[i] = bone.frames[i] * parentTransform;
                        }
                    }
                }
            }

            // Multiply the animation transforms by the binding transform.
            foreach (var animation in animations)
            {
                foreach (var bone in animation.Value.bones)
                {
                    // Sanity.
                    if (boneNameToID.ContainsKey(bone.name))
                    {
                        int    id          = boneNameToID[bone.name];
                        GLBone bindingBone = bindingBones.bones[id];

                        for (int i = 0; i < bone.frames.Count; ++i)
                        {
                            bone.frames[i] = bindingBone.transform * bone.frames[i];
                        }
                    }
                }
            }

            // Create the OpenGL objects.
            result = Create(vertexPositions, vertexNormals, vertexTextureCoordinates,
                            vertexBoneIndices, vertexBoneWeights, indices, logger);

            return(result);
        }
コード例 #13
0
 static void SKNTest()
 {
     SKNFile skn = new SKNFile("Pyke_Base.Pyke.skn");
 }
コード例 #14
0
        private void handle(WADEntry entry, string namePath)
        {
            if (namePath.ToLower().EndsWith(".dds"))
            {
                if (mode == 0)
                {
                    mode = 1;
                    _viewPort.Visibility              = Visibility.Collapsed;
                    _previewImage.Visibility          = Visibility.Visible;
                    _previewTextureComboBox.IsEnabled = false;
                    _previewMeshesComboBox.IsEnabled  = false;
                }

                _previewTypeLabel.Content = "Type: DirectDraw Surface";
                _previewNameLabel.Content = "Name: " + namePath.Split('/').Last();

                var stream = new MemoryStream();
                var image  = DDS.LoadImage(entry.GetContent(true));
                image.Save(stream, ImageFormat.Png);


                var imageSource = new BitmapImage();
                imageSource.CacheOption = BitmapCacheOption.OnLoad;
                imageSource.BeginInit();
                imageSource.StreamSource = stream;
                imageSource.EndInit();
                imageSource.Freeze();
                _previewImage.Dispatcher.BeginInvoke(new Action(() =>
                {
                    _previewImage.Source = imageSource;
                    _previewImage.Width  = image.Width;
                    _previewImage.Height = image.Height;
                }));
                return;
            }

            if (mode == 1)
            {
                mode = 0;
                _previewImage.Visibility = Visibility.Collapsed;
                _viewPort.Visibility     = Visibility.Visible;
            }

            clearUp();
            _previewTextureComboBox.IsEnabled = true;
            _previewMeshesComboBox.IsEnabled  = true;

            if (!_previewExpander.IsExpanded)
            {
                _previewExpander.IsExpanded = true;
            }


            if (namePath.ToLower().EndsWith(".scb"))
            {
                _previewMeshesComboBox.IsEnabled = false;
                var model = applyMesh(new SCBFile(new MemoryStream(entry.GetContent(true))));
                _previewTypeLabel.Content = "Type: Static Object Binary";
                _previewNameLabel.Content = "Name: " + namePath.Split('/').Last();

                if (PreSelect != null)
                {
                    foreach (var wadEntry in window.Wad.Entries)
                    {
                        if (wadEntry.XXHash == PreSelect.Item2)
                        {
                            applyMaterial(wadEntry, PreSelect.Item1, model);
                            break;
                        }
                    }

                    PreSelect = null;
                }
                else
                {
                    applyMaterial(model);
                }

                return;
            }

            if (namePath.ToLower().EndsWith(".sco"))
            {
                _previewMeshesComboBox.IsEnabled = false;
                var model = applyMesh(new SCOFile(new MemoryStream(entry.GetContent(true))));
                _previewTypeLabel.Content = "Type: Static Object Mesh";
                _previewNameLabel.Content = "Name: " + namePath.Split('/').Last();

                if (PreSelect != null)
                {
                    foreach (var wadEntry in window.Wad.Entries)
                    {
                        if (wadEntry.XXHash == PreSelect.Item2)
                        {
                            applyMaterial(wadEntry, PreSelect.Item1, model);
                            break;
                        }
                    }

                    PreSelect = null;
                }
                else
                {
                    applyMaterial(model);
                }

                return;
            }

            var result = generateInfoHolder(namePath);

            if (result == null)
            {
                return;
            }

            var skn = new SKNFile(new MemoryStream(result.sknPath.GetContent(true)));

            foreach (var subMesh in skn.Submeshes)
            {
                var model = applyMesh(subMesh);
                _previewNameLabel.Content = "Name: " + namePath.Split('/').Last();

                _previewTypeLabel.Content = "Type: Simple Skin Mesh";
                if (PreSelect != null)
                {
                    foreach (var wadEntry in window.Wad.Entries)
                    {
                        if (wadEntry.XXHash == PreSelect.Item2)
                        {
                            applyMaterial(wadEntry, PreSelect.Item1, model);
                            break;
                        }
                    }
                }
                else
                {
                    if (result.textures.Count > 0)
                    {
                        applyMaterial(result.textures.First().Value, result.textures.First().Key, model);
                    }
                    else
                    {
                        applyMaterial(model);
                    }
                }
            }

            PreSelect = null;
        }
コード例 #15
0
        private bool CreateRiggedModel(LOLModel model, Logger logger)
        {
            bool result = true;

            logger.Event("Creating rigged model.");

            // Open the skn file.
            SKNFile sknFile = new SKNFile();

            if (result == true)
            {
                result = SKNReader.Read(model.skn, ref sknFile, logger);
            }

            // Open the skl file.
            SKLFile sklFile = new SKLFile();

            if (result == true)
            {
                result = SKLReader.Read(model.skl, ref sklFile, logger);
            }

            // Open the anm files.
            Dictionary <String, ANMFile> anmFiles = new Dictionary <String, ANMFile>();

            if (result == true)
            {
                foreach (var a in model.animations)
                {
                    ANMFile anmFile   = new ANMFile();
                    bool    anmResult = ANMReader.Read(a.Value, ref anmFile, logger);
                    if (anmResult == true)
                    {
                        anmFiles.Add(a.Key, anmFile);
                    }
                }
            }

            // Create the model.
            riggedModel = new GLRiggedModel();
            if (result == true)
            {
                result = riggedModel.Create(sknFile, sklFile, anmFiles, logger);
            }

            // Set up an initial animation.
            if (result == true)
            {
                if (anmFiles.Count > 0)
                {
                    riggedModel.SetCurrentAnimation(anmFiles.First().Key);
                    riggedModel.SetCurrentFrame(0, 0);
                }
            }

            //
            // Create Model Texture.
            //
            if (result == true)
            {
                // Texture stored in RAF file.
                result = CreateTexture(model.texture, TextureTarget.Texture2D,
                                       GLTexture.SupportedImageEncodings.DDS, logger);

                // Store it in our new model file.
                if (result == true)
                {
                    String name = model.texture.FileName;
                    int    pos  = name.LastIndexOf("/");
                    name = name.Substring(pos + 1);

                    riggedModel.TextureName = name;
                }
            }

            if (result == false)
            {
                logger.Error("Failed to create rigged model.");
            }

            return(result);
        }
コード例 #16
0
        /// <summary>
        /// 导出skn为obj
        /// </summary>
        /// <param name="selectedPath"></param>
        /// <param name="entries"></param>
        private void ExtractWADEntriesObj(string selectedPath, List <WADEntry> entries)
        {
            this.progressBarWadExtraction.Maximum = entries.Count;
            this.IsEnabled = false;

            BackgroundWorker wadExtractor = new BackgroundWorker
            {
                WorkerReportsProgress = true
            };

            wadExtractor.ProgressChanged += (sender, args) =>
            {
                this.progressBarWadExtraction.Value = args.ProgressPercentage;
            };

            wadExtractor.DoWork += (sender, e) =>
            {
                Dictionary <string, byte[]> fileEntries = new Dictionary <string, byte[]>();
                double progress = 0;
                bool   createPackedMappingFile  = false;
                string packedMappingFileContent = "";

                foreach (WADEntry entry in entries)
                {
                    byte[] entryData = entry.GetContent(true);
                    string entryName;
                    if (StringDictionary.ContainsKey(entry.XXHash))
                    {
                        entryName = StringDictionary[entry.XXHash];

                        if (Regex.IsMatch(entryName, @"^DATA/.*_Skins_Skin.*\.bin$"))
                        {
                            createPackedMappingFile = true;
                            entryName = entry.XXHash.ToString("X16") + ".bin";
                            packedMappingFileContent += string.Format("{0} = {1}\n", entryName, StringDictionary[entry.XXHash]);
                        }
                        else
                        {
                            Directory.CreateDirectory(Path.Combine(selectedPath, Path.GetDirectoryName(entryName) ?? ""));
                        }
                    }
                    else
                    {
                        entryName = entry.XXHash.ToString("X16") + "." + Utilities.GetEntryExtension(Utilities.GetLeagueFileExtensionType(entryData));
                    }

                    fileEntries.Add(entryName, entryData);
                    progress += 0.5;
                    wadExtractor.ReportProgress((int)progress);
                }

                if ((bool)this.Config["ParallelExtraction"])
                {
                    Parallel.ForEach(fileEntries, entry =>
                    {
                        //File.WriteAllBytes(Path.Combine(selectedPath, entry.Key), entry.Value);
                        SKNFile sknFile = new SKNFile(new MemoryStream(entry.Value));
                        sknFile.Write(Path.Combine(selectedPath, entry.Key));
                        progress += 0.5;
                        wadExtractor.ReportProgress((int)progress);
                    });
                }
                else
                {
                    foreach (KeyValuePair <string, byte[]> entry in fileEntries)
                    {
                        File.WriteAllBytes(Path.Combine(selectedPath, entry.Key), entry.Value);

                        progress += 0.5;
                        wadExtractor.ReportProgress((int)progress);
                    }
                }

                if (createPackedMappingFile)
                {
                    File.WriteAllText(Path.Combine(selectedPath, "OBSIDIAN_PACKED_MAPPING.txt"), packedMappingFileContent);
                }
            };

            wadExtractor.RunWorkerCompleted += (sender, args) =>
            {
                if (args.Error != null)
                {
                    MessageBox.Show(string.Format("An error occured:\n{0}", args.Error), "", MessageBoxButton.OK, MessageBoxImage.Error);
                    Logger.Error(string.Format("WAD extraction failed:\n{0}", args.Error));
                }
                else
                {
                    MessageBox.Show("Extraction Successful!", "", MessageBoxButton.OK, MessageBoxImage.Information);
                    Logger.Info("WAD Extraction Successful!");
                }

                this.progressBarWadExtraction.Maximum = 100;
                this.progressBarWadExtraction.Value   = 100;
                this.IsEnabled = true;
            };

            wadExtractor.RunWorkerAsync();
        }