private static void CalculateNormals(List <STVertex> vertices, List <uint> f)
        {
            if (vertices.Count < 3)
            {
                return;
            }

            Vector3[] normals = new Vector3[vertices.Count];

            for (int i = 0; i < normals.Length; i++)
            {
                normals[i] = new Vector3(0, 0, 0);
            }

            for (int i = 0; i < f.Count; i += 3)
            {
                STVertex v1  = vertices[(int)f[i]];
                STVertex v2  = vertices[(int)f[i + 1]];
                STVertex v3  = vertices[(int)f[i + 2]];
                Vector3  nrm = CalculateNormal(v1, v2, v3);

                normals[f[i + 0]] += nrm * (nrm.Length / 2);
                normals[f[i + 1]] += nrm * (nrm.Length / 2);
                normals[f[i + 2]] += nrm * (nrm.Length / 2);
            }

            for (int i = 0; i < normals.Length; i++)
            {
                vertices[i].Normal = normals[i].Normalized();
            }
        }
Ejemplo n.º 2
0
        private static STVertex ReadLayout3(this FileReader reader, uint hash)
        {
            uint stride = GetStride(hash);

            STVertex vertex = new STVertex();

            vertex.TexCoords = new Vector2[2];
            if (stride >= 0x1C)
            {
                vertex.Colors = new Vector4[1];
            }

            vertex.Position = new Vector3(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle());
            vertex.Normal   = new Vector3(
                reader.ReadSByte() / 255f,
                reader.ReadSByte() / 255f,
                reader.ReadSByte() / 255f).Normalized();
            reader.ReadSByte();
            vertex.TexCoords[0] = new Vector2(
                reader.ReadInt16() / 1024.0f,
                reader.ReadInt16() / 1024.0f);
            vertex.TexCoords[1] = new Vector2(
                reader.ReadInt16() / 1024.0f,
                reader.ReadInt16() / 1024.0f);

            if (stride >= 0x1C)
            {
                vertex.Colors[0] = new Vector4(
                    reader.ReadByte() / 255.0f,
                    reader.ReadByte() / 255.0f,
                    reader.ReadByte() / 255.0f,
                    reader.ReadByte() / 255.0f);
            }
            return(vertex);
        }
Ejemplo n.º 3
0
        public Dictionary <string, KeyGroup> LoadKeyGroups()
        {
            //Load the vertex buffer into the helper to easily access the data.
            VertexBufferHelper helper = new VertexBufferHelper(VertexBuffer, ParentFile.ByteOrder);

            int index = 0;

            Dictionary <string, KeyGroup> keyGroups = new Dictionary <string, KeyGroup>();

            foreach (var keyShape in Shape.KeyShapes)
            {
                var group = new KeyGroup();

                //Loop through all the vertex data and load it into our vertex data
                group.Vertices = new List <STVertex>();

                //Get all the necessary attributes
                var positions = TryGetValues(helper, $"_p{index}");
                for (int i = 0; i < positions.Length; i++)
                {
                    var vertex = new STVertex();
                    vertex.Position = new Vector3(positions[i].X, positions[i].Y, positions[i].Z);
                    group.Vertices.Add(vertex);
                }
                if (group.Vertices.Count > 0)
                {
                    keyGroups.Add(keyShape.Key, group);
                }

                index++;
            }
            return(keyGroups);
        }
Ejemplo n.º 4
0
        public STGenericModel ToGeneric()
        {
            if (Model != null)
            {
                return(Model);
            }

            var model = new STGenericModel(FileInfo.FileName);

            /*     var msh = new STGenericMesh() { Name = $"Mesh0" };
             *   model.Meshes.Add(msh);
             *
             *   List<STVertex> verts = new List<STVertex>();
             *   for (int v = 0; v < MorphData.Positions.Count; v++)
             *   {
             *       STVertex vertex = new STVertex();
             *       vertex.Position = MorphData.Positions[v];
             *       verts.Add(vertex);
             *   }
             *
             *   STPolygonGroup group = new STPolygonGroup();
             *   group.PrimitiveType = STPrimitiveType.Points;
             *   msh.PolygonGroups.Add(group);
             *
             *   msh.Vertices.AddRange(verts);
             *   msh.Optmize(group);
             */

            for (int i = 0; i < MorphData.MorphGroups.Count; i++)
            {
                var mesh = new STGenericMesh()
                {
                    Name = $"Mesh{i}"
                };
                model.Meshes.Add(mesh);

                var morphData = MorphData.MorphGroups[i];

                STPolygonGroup group = new STPolygonGroup();
                group.PrimitiveType = STPrimitiveType.Triangles;
                mesh.PolygonGroups.Add(group);

                List <STVertex> verts = new List <STVertex>();
                for (int v = 0; v < morphData.Positions.Count; v++)
                {
                    STVertex vertex = new STVertex();
                    vertex.Position = morphData.Positions[v];
                    verts.Add(vertex);
                }

                verts = ConvertTriStrips(verts);
                mesh.Vertices.AddRange(verts);

                mesh.Optmize(group);
            }

            Model = model;
            return(model);
        }
        private static Vector3 CalculateNormal(STVertex v1, STVertex v2, STVertex v3)
        {
            Vector3 U = v2.Position - v1.Position;
            Vector3 V = v3.Position - v1.Position;

            // Don't normalize here, so surface area can be calculated.
            return(Vector3.Cross(U, V));
        }
Ejemplo n.º 6
0
        private static STVertex ReadLayout4(this FileReader reader, uint hash)
        {
            uint stride = GetStride(hash);

            STVertex vertex = new STVertex();

            vertex.Position = new Vector3(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle());
            return(vertex);
        }
Ejemplo n.º 7
0
        private static STVertex ReadLayout1(this FileReader reader, uint hash)
        {
            uint stride = GetStride(hash);

            STVertex vertex = new STVertex();

            vertex.TexCoords = new Vector2[1];

            long pos = reader.Position;

            vertex.Position = new Vector3(
                UShortToFloatDecode(reader.ReadInt16()),
                UShortToFloatDecode(reader.ReadInt16()),
                UShortToFloatDecode(reader.ReadInt16()));

            vertex.Normal = new Vector3(
                reader.ReadSByte() / 255f,
                reader.ReadSByte() / 255f,
                reader.ReadSByte() / 255f);
            byte boneIndex1 = reader.ReadByte();

            vertex.TexCoords[0] = new Vector2(
                reader.ReadInt16() / 1024.0f,
                reader.ReadInt16() / 1024.0f);

            if (stride >= 22)
            {
                byte     boneIndex2 = reader.ReadByte();
                byte     boneIndex3 = reader.ReadByte();
                ushort[] weights    = reader.ReadUInt16s(3);

                vertex.BoneIndices.Add(boneIndex2 / 3);
                vertex.BoneIndices.Add(boneIndex3 / 3);
                if (weights[2] != 0)
                {
                    vertex.BoneIndices.Add(boneIndex1 / 3);
                }

                vertex.BoneWeights.Add(weights[0] / 16384.0f);
                vertex.BoneWeights.Add(weights[1] / 16384.0f);
                if (weights[2] != 0)
                {
                    vertex.BoneWeights.Add(weights[2] / 16384.0f);
                }
            }

            if (stride == 26)
            {
            }

            return(vertex);
        }
Ejemplo n.º 8
0
        //Geometry shader effects ie uvslidingmaterialgs.
        private static STVertex ReadLayout6(this FileReader reader, uint hash)
        {
            //This requires geoemtry shader so skip it atm
            return(new STVertex());

            uint stride = GetStride(hash);

            STVertex vertex = new STVertex();

            vertex.TexCoords = new Vector2[1];

            vertex.Position = new Vector3(
                reader.ReadSingle(),
                reader.ReadSingle(),
                reader.ReadSingle());
            return(vertex);
        }
        public static List <STVertex> ReadDisplayLists(Stream stream, Stream dataStream,
                                                       GXVertexLayout[] layouts, Config config = null, ushort[] matrixIndices = null)
        {
            if (config == null)
            {
                config = new Config();
            }

            int numColors    = GetColorCount(layouts);
            int numTexCoords = GetTexCoordsCount(layouts);

            bool hasVertexColors = layouts.Any(x => x.Attribute == GXAttributes.Color0);

            List <GXOpCodes> operations = new List <GXOpCodes>();

            List <STVertex> vertices = new List <STVertex>();

            using (var dataReader = new FileReader(dataStream, true))
                using (var reader = new FileReader(stream, true)) {
                    dataReader.SetByteOrder(true);
                    reader.SetByteOrder(true);

                    while (!reader.EndOfStream)
                    {
                        GXOpCodes opCode = (GXOpCodes)(reader.ReadByte());
                        if (opCode == GXOpCodes.NOOP)
                        {
                            continue;
                        }

                        opCode = (GXOpCodes)((byte)opCode + config.OpCodeShift);

                        if (!operations.Contains(opCode))
                        {
                            operations.Add(opCode);
                        }

                        List <STVertex> verts = new List <STVertex>();

                        ushort numVertices = reader.ReadUInt16();
                        for (int v = 0; v < numVertices; v++)
                        {
                            STVertex vertex = new STVertex();
                            vertex.TexCoords = new OpenTK.Vector2[numTexCoords];
                            if (hasVertexColors)
                            {
                                vertex.Colors = new OpenTK.Vector4[numColors];
                            }

                            for (int l = 0; l < layouts.Length; l++)
                            {
                                var index = ReadLayout(reader, layouts[l]);
                                ParseData(vertex, dataReader, layouts[l], index, matrixIndices);
                            }
                            verts.Add(vertex);
                        }

                        if (opCode == GXOpCodes.DRAW_TRIANGLES)
                        {
                            vertices.AddRange(verts);
                        }
                        else if (opCode == GXOpCodes.DRAW_TRIANGLE_FAN)
                        {
                            verts = ConvertTriFans(verts);
                            vertices.AddRange(verts);
                        }
                        else if (opCode == GXOpCodes.DRAW_TRIANGLE_STRIP)
                        {
                            verts = ConvertTriStrips(verts);
                            vertices.AddRange(verts);
                        }
                        else if (opCode == GXOpCodes.DRAW_QUADS || opCode == GXOpCodes.DRAW_QUADS_2)
                        {
                            verts = ConvertQuads(verts);
                            vertices.AddRange(verts);
                        }
                        else
                        {
                            Console.WriteLine($"Unknown opCode {opCode}");
                            vertices.AddRange(verts);
                        }
                    }
                }
            operations.Clear();
            return(vertices);
        }
        private static void ParseData(STVertex vertex, FileReader dataReader, GXVertexLayout layout, int index, ushort[] matrixIndices)
        {
            int numElements = GetElementCount(layout.Attribute);
            int stride      = GetDataStride(layout.CompType) * numElements;

            if (IsColor(layout))
            {
                stride = GetColorDataStride(layout.CompType);
            }

            using (dataReader.TemporarySeek(layout.DataOffset + (index * stride), SeekOrigin.Begin))
            {
                // Console.WriteLine($"attribute {layout.Attribute} stride {stride} index {index}");
                switch (layout.Attribute)
                {
                case GXAttributes.Position:
                {
                    float X = ReadDataLayout(dataReader, layout);
                    float Y = ReadDataLayout(dataReader, layout);
                    float Z = ReadDataLayout(dataReader, layout);
                    vertex.Position = new OpenTK.Vector3(X, Y, Z);
                }
                break;

                case GXAttributes.Normal:
                {
                    float X = ReadDataLayout(dataReader, layout);
                    float Y = ReadDataLayout(dataReader, layout);
                    float Z = ReadDataLayout(dataReader, layout);
                    vertex.Normal = new OpenTK.Vector3(X, Y, Z).Normalized();
                }
                break;

                case GXAttributes.NormalBinormalTangent:
                {
                    float NormalX   = ReadDataLayout(dataReader, layout);
                    float NormalY   = ReadDataLayout(dataReader, layout);
                    float NormalZ   = ReadDataLayout(dataReader, layout);
                    float BinormalX = ReadDataLayout(dataReader, layout);
                    float BinormalY = ReadDataLayout(dataReader, layout);
                    float BinormalZ = ReadDataLayout(dataReader, layout);
                    float TangentX  = ReadDataLayout(dataReader, layout);
                    float TangentY  = ReadDataLayout(dataReader, layout);
                    float TangentZ  = ReadDataLayout(dataReader, layout);
                    vertex.Normal    = new OpenTK.Vector3(NormalX, NormalY, NormalZ).Normalized();
                    vertex.Bitangent = new OpenTK.Vector4(BinormalX, BinormalY, BinormalZ, 1);
                    vertex.Tangent   = new OpenTK.Vector4(TangentX, TangentY, TangentZ, 1);
                }
                break;

                case GXAttributes.TexCoord0:
                case GXAttributes.TexCoord1:
                case GXAttributes.TexCoord2:
                case GXAttributes.TexCoord3:
                case GXAttributes.TexCoord4:
                case GXAttributes.TexCoord5:
                case GXAttributes.TexCoord6:
                case GXAttributes.TexCoord7:
                {
                    int   channel = GetChannel(layout.Attribute);
                    float X       = ReadDataLayout(dataReader, layout);
                    float Y       = ReadDataLayout(dataReader, layout);
                    vertex.TexCoords[channel] = new OpenTK.Vector2(X, Y);
                }
                break;

                case GXAttributes.Color0:
                case GXAttributes.Color1:
                {
                    int channel = GetChannel(layout.Attribute);
                    var color   = ReadDataColorLayout(dataReader, layout);
                    vertex.Colors[0] = new OpenTK.Vector4(color.X, color.Y, color.Z, color.W);
                }
                break;

                case GXAttributes.PosNormMatrix:
                {
                    if (index != -1)
                    {
                        int boneID = index / 3;
                        if (matrixIndices != null)
                        {
                            boneID = matrixIndices[index / 3];
                        }
                        Console.WriteLine($"BONEID {index} real {boneID}");

                        vertex.BoneIndices.Add(boneID);
                        vertex.BoneWeights.Add(1.0f);
                    }
                }
                break;
                }
            }
        }
Ejemplo n.º 11
0
        private static void ParseData(STVertex vertex, FileReader dataReader, GXVertexLayout layout, int index)
        {
            int numElements = GetElementCount(layout.Attribute);
            int stride      = GetDataStride(layout.CompType) * numElements;

            if (IsColor(layout))
            {
                stride = GetColorDataStride(layout.CompType);
            }

            using (dataReader.TemporarySeek(layout.DataOffset + (index * stride), SeekOrigin.Begin))
            {
                // Console.WriteLine($"attribute {layout.Attribute} stride {stride} index {index}");
                switch (layout.Attribute)
                {
                case GXAttributes.Position:
                {
                    float X = ReadDataLayout(dataReader, layout);
                    float Y = ReadDataLayout(dataReader, layout);
                    float Z = ReadDataLayout(dataReader, layout);
                    vertex.Position = new OpenTK.Vector3(X, Y, Z);
                }
                break;

                case GXAttributes.Normal:
                {
                    float X = ReadDataLayout(dataReader, layout);
                    float Y = ReadDataLayout(dataReader, layout);
                    float Z = ReadDataLayout(dataReader, layout);
                    vertex.Normal = new OpenTK.Vector3(X, Y, Z).Normalized();
                }
                break;

                case GXAttributes.TexCoord0:
                case GXAttributes.TexCoord1:
                case GXAttributes.TexCoord2:
                case GXAttributes.TexCoord3:
                case GXAttributes.TexCoord4:
                case GXAttributes.TexCoord5:
                case GXAttributes.TexCoord6:
                case GXAttributes.TexCoord7:
                {
                    int   channel = (int)(layout.Attribute - GXAttributes.TexCoord0);
                    float X       = ReadDataLayout(dataReader, layout);
                    float Y       = ReadDataLayout(dataReader, layout);
                    vertex.TexCoords[0] = new OpenTK.Vector2(X, Y);
                }
                break;

                case GXAttributes.Color0:
                case GXAttributes.Color1:
                {
                    int channel = (int)(layout.Attribute - GXAttributes.Color0);
                    var color   = ReadDataColorLayout(dataReader, layout);
                    vertex.Colors[0] = new OpenTK.Vector4(color.X, color.Y, color.Z, color.W);
                }
                break;

                case GXAttributes.PosNormMatrix:
                {
                    if (index != -1)
                    {
                        int boneID = index / 3;
                        vertex.BoneIndices.Add(boneID);
                        vertex.BoneWeights.Add(1.0f);
                    }
                }
                break;
                }
            }
        }
Ejemplo n.º 12
0
        public STGenericModel ToGeneric()
        {
            if (Model != null)
            {
                return(Model);
            }

            var model       = new STGenericModel(FileInfo.FileName);
            var sectionData = Header.FileHeader.SectionData;

            foreach (var bone in sectionData.SkeletonChunk.Bones)
            {
                model.Skeleton.Bones.Add(new STBone(model.Skeleton)
                {
                    Name     = $"Bone{bone.ID}",
                    Position = new Vector3(
                        bone.Translation.X,
                        bone.Translation.Y,
                        bone.Translation.Z),
                    Scale = new Vector3(
                        bone.Scale.X,
                        bone.Scale.Y,
                        bone.Scale.Z),
                    EulerRotation = new Vector3(
                        bone.Rotation.X,
                        bone.Rotation.Y,
                        bone.Rotation.Z),
                    ParentIndex = bone.ParentIndex,
                });
            }

            model.Skeleton.Reset();
            model.Skeleton.Update();

            foreach (var tex in sectionData.TextureChunk.Textures)
            {
                model.Textures.Add(new CTXB.TextureWrapper(tex)
                {
                    Name = $"Texture{model.Textures.Count}"
                });
            }

            foreach (var mat in sectionData.MaterialChunk.Materials)
            {
                STGenericMaterial genericMat = new STGenericMaterial();
                genericMat.Name = $"Material{model.Materials.Count}";
                model.Materials.Add(genericMat);

                bool HasDiffuse = false;
                foreach (var tex in mat.TextureMaps)
                {
                    if (tex.TextureIndex != -1)
                    {
                        STGenericTextureMap matTexture = new STGenericTextureMap();
                        genericMat.TextureMaps.Add(matTexture);

                        if (tex.TextureIndex < model.Textures.Count)
                        {
                            matTexture.Name = model.Textures[tex.TextureIndex].Name;
                        }

                        if (!HasDiffuse && matTexture.Name != "bg_syadowmap") //Quick hack till i do texture env stuff
                        {
                            matTexture.Type = STTextureType.Diffuse;
                            HasDiffuse      = true;
                        }
                    }
                }
            }

            var shapeData = sectionData.SkeletalMeshChunk.ShapeChunk;
            var meshData  = sectionData.SkeletalMeshChunk.MeshChunk;

            foreach (var mesh in meshData.Meshes)
            {
                STGenericMesh genericMesh = new STGenericMesh();
                genericMesh.Name = $"Mesh_{model.Meshes.Count}";
                model.Meshes.Add(genericMesh);

                var shape = shapeData.SeperateShapes[(int)mesh.SepdIndex];

                List <ushort> SkinnedBoneTable = new List <ushort>();
                foreach (var prim in shape.Primatives)
                {
                    if (prim.BoneIndexTable != null)
                    {
                        SkinnedBoneTable.AddRange(prim.BoneIndexTable);
                    }
                }

                //Now load the vertex and face data
                if (shape.Position.VertexData != null)
                {
                    int VertexCount = shape.Position.VertexData.Length;
                    for (int v = 0; v < VertexCount; v++)
                    {
                        STVertex vert = new STVertex();
                        vert.TexCoords = new Vector2[1];

                        vert.Position = new OpenTK.Vector3(
                            shape.Position.VertexData[v].X,
                            shape.Position.VertexData[v].Y,
                            shape.Position.VertexData[v].Z);

                        if (shape.Normal.VertexData != null && shape.Normal.VertexData.Length > v)
                        {
                            vert.Normal = new OpenTK.Vector3(
                                shape.Normal.VertexData[v].X,
                                shape.Normal.VertexData[v].Y,
                                shape.Normal.VertexData[v].Z).Normalized();
                        }

                        if (shape.Color.VertexData != null && shape.Color.VertexData.Length > v)
                        {
                            vert.Colors = new Vector4[1]
                            {
                                new OpenTK.Vector4(
                                    shape.Color.VertexData[v].X,
                                    shape.Color.VertexData[v].Y,
                                    shape.Color.VertexData[v].Z,
                                    shape.Color.VertexData[v].W).Normalized()
                            };
                        }

                        if (shape.TexCoord0.VertexData != null && shape.TexCoord0.VertexData.Length > v)
                        {
                            vert.TexCoords[0] = new OpenTK.Vector2(
                                shape.TexCoord0.VertexData[v].X,
                                1 - shape.TexCoord0.VertexData[v].Y);
                        }

                        if (shape.TexCoord1.VertexData != null)
                        {
                        }

                        if (shape.TexCoord2.VertexData != null)
                        {
                        }

                        for (int i = 0; i < 16; i++)
                        {
                            if (i < shape.Primatives[0].BoneIndexTable.Length)
                            {
                                int boneId = shape.Primatives[0].BoneIndexTable[i];

                                if (shape.Primatives[0].SkinningMode == SkinningMode.RIGID_SKINNING)
                                {
                                    vert.Position = Vector3.TransformPosition(vert.Position, model.Skeleton.Bones[boneId].Transform);
                                    vert.Normal   = Vector3.TransformNormal(vert.Position, model.Skeleton.Bones[boneId].Transform);
                                }
                            }
                        }

                        bool HasSkinning = shape.Primatives[0].SkinningMode != SkinningMode.SINGLE_BONE &&
                                           shape.BoneIndices.Type == CmbDataType.UByte; //Noclip checks the type for ubyte so do the same

                        bool HasWeights = shape.Primatives[0].SkinningMode == SkinningMode.SMOOTH_SKINNING;

                        if (shape.BoneIndices.VertexData != null && HasSkinning && shape.BoneIndices.VertexData.Length > v)
                        {
                            var BoneIndices = shape.BoneIndices.VertexData[v];
                            for (int j = 0; j < shape.boneDimension; j++)
                            {
                                if (BoneIndices[j] < SkinnedBoneTable.Count)
                                {
                                    vert.BoneIndices.Add((int)SkinnedBoneTable[(int)BoneIndices[j]]);
                                }
                                //   Console.WriteLine("boneIds " + BoneIndices[j]);

                                //    ushort index = shape.Primatives[0].BoneIndexTable[(uint)BoneIndices[j]];
                            }
                        }
                        if (shape.BoneWeights.VertexData != null && HasWeights && shape.BoneWeights.VertexData.Length > v)
                        {
                            var BoneWeights = shape.BoneWeights.VertexData[v];
                            for (int j = 0; j < shape.boneDimension; j++)
                            {
                                vert.BoneWeights.Add(BoneWeights[j]);
                            }
                        }

                        genericMesh.Vertices.Add(vert);
                    }
                }

                foreach (var prim in shape.Primatives)
                {
                    STPolygonGroup group = new STPolygonGroup();
                    genericMesh.PolygonGroups.Add(group);
                    group.MaterialIndex = mesh.MaterialIndex;

                    // for (int i = 0; i < prim.Primatives[0].Indices.Length; i++)
                    //      group.Faces.Add(prim.Primatives[0].Indices[i]);
                }
            }

            Model = model;
            return(model);
        }
Ejemplo n.º 13
0
        private static void ParseVertexSource(ref STVertex vertex, ColladaScene scene, source source,
                                              int numTexCoordChannels, int numColorChannels, int stride, int index, int set, string semantic)
        {
            float_array array = source.Item as float_array;

            switch (semantic)
            {
            case "VERTEX":
            case "POSITION":
                vertex.Position = new Vector3(
                    (float)array.Values[index + 0],
                    (float)array.Values[index + 1],
                    (float)array.Values[index + 2]);
                vertex.Position = ApplyUintScaling(scene, vertex.Position);
                if (scene.UpAxisType == UpAxisType.Z_UP)
                {
                    vertex.Position = new Vector3(
                        vertex.Position.X,
                        vertex.Position.Z,
                        -vertex.Position.Y);
                }
                break;

            case "NORMAL":
                vertex.Normal = new Vector3(
                    (float)array.Values[index + 0],
                    (float)array.Values[index + 1],
                    (float)array.Values[index + 2]);
                if (scene.UpAxisType == UpAxisType.Z_UP)
                {
                    vertex.Normal = new Vector3(
                        vertex.Normal.X,
                        vertex.Normal.Z,
                        -vertex.Normal.Y);
                }
                break;

            case "TEXCOORD":
                vertex.TexCoords[set] = new Vector2(
                    (float)array.Values[index + 0],
                    (float)array.Values[index + 1]);
                break;

            case "COLOR":
                float R = 1, G = 1, B = 1, A = 1;
                if (stride >= 1)
                {
                    R = (float)array.Values[index + 0];
                }
                if (stride >= 2)
                {
                    G = (float)array.Values[index + 1];
                }
                if (stride >= 3)
                {
                    B = (float)array.Values[index + 2];
                }
                if (stride >= 4)
                {
                    A = (float)array.Values[index + 3];
                }
                vertex.Colors[set] = new Vector4(R, G, B, A);
                break;
            }

            //We need to make sure the axis is converted to Z up

            /*  switch (scene.UpAxisType)
             * {
             *    case UpAxisType.X_UP:
             *        break;
             *    case UpAxisType.Y_UP:
             *        Vector3 pos = vertex.Position;
             *        Vector3 nrm = vertex.Normal;
             *        //   vertex.Position = new Vector3(pos.X, pos.Z, pos.Y);
             *        //    vertex.Normal = new Vector3(nrm.X, nrm.Z, nrm.Y);
             *        break;
             * }*/
        }
Ejemplo n.º 14
0
        private static void ConvertPolygon(ColladaScene scene, STGenericMesh mesh, mesh daeMesh,
                                           InputLocalOffset[] inputs, List <BoneWeight[]> boneWeights,
                                           library_materials materials, string material, string polys, int polyCount, string vcount = "")
        {
            List <uint> faces = new List <uint>();

            STPolygonGroup group = new STPolygonGroup();

            mesh.PolygonGroups.Add(group);
            group.MaterialIndex = DaeUtility.FindMaterialIndex(materials, material);

            string[] indices     = polys.Trim(' ').Split(' ');
            string[] vertexCount = new string[0];
            if (vcount != string.Empty)
            {
                vertexCount = vcount.Trim(' ').Split(' ');
            }

            int stride = 0;

            for (int i = 0; i < inputs.Length; i++)
            {
                stride = Math.Max(0, (int)inputs[i].offset + 1);
            }

            //Create a current list of all the vertices
            //Use a list to expand duplicate indices
            List <Vertex> vertices     = new List <Vertex>();
            var           vertexSource = DaeUtility.FindSourceFromInput(daeMesh.vertices.input[0], daeMesh.source);
            var           floatArr     = vertexSource.Item as float_array;

            for (int v = 0; v < (int)floatArr.count / 3; v++)
            {
                vertices.Add(new Vertex(vertices.Count, new List <int>()));
            }

            var indexStride = (indices.Length / 3) / polyCount;

            for (int i = 0; i < polyCount; i++)
            {
                int count = 3;
                if (vertexCount.Length > i)
                {
                    count = Convert.ToInt32(vertexCount[i]);
                }

                for (int v = 0; v < count; v++)
                {
                    List <int> semanticIndices = new List <int>();
                    for (int j = 0; j < inputs.Length; j++)
                    {
                        int faceOffset = (indexStride * 3) * i;
                        int index      = Convert.ToInt32(indices[faceOffset + (v * indexStride) + (int)inputs[j].offset]);
                        semanticIndices.Add(index);
                    }

                    BoneWeight[] boneWeightData = new BoneWeight[0];
                    if (boneWeights?.Count > semanticIndices[0])
                    {
                        boneWeightData = boneWeights[semanticIndices[0]];
                    }

                    VertexLoader.LoadVertex(ref faces, ref vertices, semanticIndices, boneWeightData);
                }
            }

            int numTexCoordChannels = 0;
            int numColorChannels    = 0;

            //Find them in both types of inputs
            for (int i = 0; i < inputs.Length; i++)
            {
                if (inputs[i].semantic == "TEXCOORD")
                {
                    numTexCoordChannels++;
                }
                if (inputs[i].semantic == "COLOR")
                {
                    numColorChannels++;
                }
            }

            for (int i = 0; i < daeMesh.vertices.input.Length; i++)
            {
                if (daeMesh.vertices.input[i].semantic == "TEXCOORD")
                {
                    numTexCoordChannels++;
                }
                if (daeMesh.vertices.input[i].semantic == "COLOR")
                {
                    numColorChannels++;
                }
            }


            for (int i = 0; i < vertices.Count; i++)
            {
                if (!vertices[i].IsSet)
                {
                    vertices.Remove(vertices[i]);
                }
            }

            bool hasNormals = false;

            foreach (var daeVertex in vertices)
            {
                if (daeVertex.semanticIndices.Count == 0)
                {
                    continue;
                }

                STVertex vertex = new STVertex();
                vertex.TexCoords   = new Vector2[numTexCoordChannels];
                vertex.Colors      = new Vector4[numColorChannels];
                vertex.BoneWeights = daeVertex.BoneWeights.ToList();
                mesh.Vertices.Add(vertex);

                //DAE has 2 inputs. Vertex and triangle inputs
                //Triangle inputs use indices over vertex inputs which only use one
                //Triangle inputs allow multiple color/uv sets unlike vertex inputs
                //Certain programs ie Noesis DAEs use vertex inputs. Most programs use triangle inputs
                for (int j = 0; j < daeMesh.vertices.input.Length; j++)
                {
                    //Vertex inputs only use the first index
                    var    vertexInput = daeMesh.vertices.input[j];
                    source source      = DaeUtility.FindSourceFromInput(vertexInput, daeMesh.source);
                    if (source == null)
                    {
                        continue;
                    }
                    if (vertexInput.semantic == "NORMAL")
                    {
                        hasNormals = true;
                    }

                    int dataStride = (int)source.technique_common.accessor.stride;
                    int index      = daeVertex.semanticIndices[0] * dataStride;

                    ParseVertexSource(ref vertex, scene, source, numTexCoordChannels, numColorChannels,
                                      dataStride, index, 0, vertexInput.semantic);
                }

                for (int i = 0; i < inputs.Length; i++)
                {
                    var    input  = inputs[i];
                    source source = DaeUtility.FindSourceFromInput(input, daeMesh.source);
                    if (source == null)
                    {
                        continue;
                    }
                    if (input.semantic == "NORMAL")
                    {
                        hasNormals = true;
                    }

                    int dataStride = (int)source.technique_common.accessor.stride;
                    int index      = daeVertex.semanticIndices[i] * dataStride;

                    ParseVertexSource(ref vertex, scene, source, numTexCoordChannels, numColorChannels,
                                      dataStride, index, (int)input.set, input.semantic);
                }
            }

            group.Faces = faces;

            if (!hasNormals)
            {
                CalculateNormals(mesh.Vertices, faces);
            }
            if (scene.Settings.RemoveDuplicateVerts)
            {
                RemoveDuplicateVerts(mesh.Vertices, faces);
            }
        }
Ejemplo n.º 15
0
        /// <summary>
        /// Updates the current buffer from the shapes vertex buffer data.
        /// </summary>
        public void UpdateVertexBuffer(bool weighPositions = false)
        {
            //Load the vertex buffer into the helper to easily access the data.
            VertexBufferHelper helper = new VertexBufferHelper(VertexBuffer, ParentFile.ByteOrder);

            //Loop through all the vertex data and load it into our vertex data
            Vertices = new List <STVertex>();

            //Get all the necessary attributes
            var positions  = TryGetValues(helper, "_p0");
            var normals    = TryGetValues(helper, "_n0");
            var texCoords  = TryGetChannelValues(helper, "_u");
            var colors     = TryGetChannelValues(helper, "_c");
            var tangents   = TryGetValues(helper, "_t0");
            var bitangents = TryGetValues(helper, "_b0");
            var weights0   = TryGetValues(helper, "_w0");
            var indices0   = TryGetValues(helper, "_i0");
            var weights1   = TryGetValues(helper, "_w1");
            var indices1   = TryGetValues(helper, "_i1");

            var boneIndexList = ParentSkeleton.Skeleton.MatrixToBoneList;

            float scale = GLFrameworkEngine.GLContext.PreviewScale;

            //Get the position attribute and use the length for the vertex count
            for (int v = 0; v < positions.Length; v++)
            {
                STVertex vertex = new STVertex();
                Vertices.Add(vertex);

                vertex.Position = new Vector3(positions[v].X, positions[v].Y, positions[v].Z) * scale;
                if (normals.Length > 0)
                {
                    vertex.Normal = new Vector3(normals[v].X, normals[v].Y, normals[v].Z);
                }

                if (texCoords.Length > 0)
                {
                    vertex.TexCoords = new Vector2[texCoords.Length];
                    for (int i = 0; i < texCoords.Length; i++)
                    {
                        vertex.TexCoords[i] = new Vector2(texCoords[i][v].X, texCoords[i][v].Y);
                    }
                }
                if (colors.Length > 0)
                {
                    vertex.Colors = new Vector4[colors.Length];
                    for (int i = 0; i < colors.Length; i++)
                    {
                        vertex.Colors[i] = new Vector4(
                            colors[i][v].X, colors[i][v].Y,
                            colors[i][v].Z, colors[i][v].W);
                    }
                }

                if (tangents.Length > 0)
                {
                    vertex.Tangent = new Vector4(tangents[v].X, tangents[v].Y, tangents[v].Z, tangents[v].W);
                }
                if (bitangents.Length > 0)
                {
                    vertex.Bitangent = new Vector4(bitangents[v].X, bitangents[v].Y, bitangents[v].Z, bitangents[v].W);
                }

                if (VertexSkinCount == 0 && weighPositions)
                {
                    var bone = ParentSkeleton.Bones[Shape.BoneIndex];
                    vertex.Position = Vector3.TransformPosition(vertex.Position, bone.Transform);
                    vertex.Normal   = Vector3.TransformNormal(vertex.Normal, bone.Transform);
                }

                for (int i = 0; i < VertexBuffer.VertexSkinCount; i++)
                {
                    int   index  = -1;
                    float weight = 0.0f;

                    if (i > 3 && indices1.Length > 0)
                    {
                        index  = boneIndexList[(int)indices1[v][i - 4]];
                        weight = weights1.Length > 0 ? weights1[v][i - 4] : 1.0f;
                    }
                    else if (i <= 3)
                    {
                        index  = boneIndexList[(int)indices0[v][i]];
                        weight = weights0.Length > 0 ? weights0[v][i] : 1.0f;
                    }
                    else
                    {
                        break;
                    }

                    vertex.BoneIndices.Add(index);
                    vertex.BoneWeights.Add(weight);

                    if (VertexSkinCount == 1 && weighPositions)
                    {
                        var bone = ParentSkeleton.Bones[index];
                        vertex.Position = Vector3.TransformPosition(vertex.Position, bone.Transform);
                        vertex.Normal   = Vector3.TransformNormal(vertex.Normal, bone.Transform);
                    }
                }
            }
        }
Ejemplo n.º 16
0
        private STGenericMesh LoadMesh(ModelBlock mdl, ObjectBlock obj, MeshBlock mesh)
        {
            STGenericMesh genericMesh = new STGenericMesh();

            genericMesh.Name = obj.Name;

            var transform = obj.GetTransform();
            var meshInfo  = obj.MeshData;
            var ctx       = NitroGX.ReadCmds(meshInfo.Data);

            for (int i = 0; i < ctx.vertices.Count; i++)
            {
                STVertex vertex = new STVertex();
                vertex.Position  = ctx.vertices[i].Position;
                vertex.Normal    = ctx.vertices[i].Normal;
                vertex.TexCoords = new Vector2[1]
                {
                    ctx.vertices[i].TexCoord
                };
                vertex.Colors = new Vector4[1]
                {
                    new Vector4(ctx.vertices[i].Color / 255f,
                                ctx.vertices[i].Alpha / 255f)
                };

                vertex.Position = Vector3.TransformPosition(vertex.Position, transform);
                genericMesh.Vertices.Add(vertex);
            }

            uint[] faces = new uint[ctx.indices.Count];
            for (int i = 0; i < ctx.indices.Count; i++)
            {
                faces[i] = ctx.indices[i];
            }

            foreach (var poly in mesh.PolyGroups)
            {
                var material = mdl.Materials[poly.MaterialIndex];

                /*    uint[] polyFaces = new uint[poly.FaceCount];
                 *  for (int i = 0; i < poly.FaceCount; i++) {
                 *      polyFaces[i] = ctx.indices[poly.FaceStart + i];
                 *  }*/

                STGenericMaterial genericMaterial = new STGenericMaterial();
                genericMaterial.Name = material.Name;

                if (material.MaterialBlock.AttributeIndex != -1)
                {
                    var attribute = mdl.Attributes[material.MaterialBlock.AttributeIndex];
                    genericMaterial.TextureMaps.Add(new STGenericTextureMap()
                    {
                        Name = attribute.TextureName,
                        Type = STTextureType.Diffuse,
                    });
                }

                genericMesh.PolygonGroups.Add(new STPolygonGroup()
                {
                    PrimitiveType = STPrimitiveType.Triangles,
                    Material      = genericMaterial,
                    Faces         = faces.ToList(),
                });

                break;
            }

            return(genericMesh);
        }
Ejemplo n.º 17
0
        static void ReadBufferData(Stream bufferChunk, Dictionary <uint, int> HashToBoneID,
                                   List <ChunkTable.ChunkDataEntry> boneHashChunks, List <ModelInfo> models)
        {
            int skinningIndex = 0;

            //Lastly parse the vertex and index buffers
            using (var reader = new FileReader(bufferChunk, true))
            {
                foreach (var model in models)
                {
                    for (int i = 0; i < model.Meshes.Count; i++)
                    {
                        var mesh = model.Meshes[i];

                        //Get our bone hash index lists
                        Dictionary <int, uint> boneIDToHash = new Dictionary <int, uint>();

                        if (boneHashChunks.Count > skinningIndex)
                        {
                            var  boneHashChunk = boneHashChunks[skinningIndex];
                            uint count         = (uint)boneHashChunk.Data.Length / 4;
                            var  hashes        = boneHashChunk.ReadPrimitive <uint>(count);
                            for (int j = 0; j < count; j++)
                            {
                                boneIDToHash.Add(j, hashes[j]);
                            }
                        }

                        reader.SeekBegin(mesh.MeshHeader.IndexOffset);

                        mesh.Faces = new uint[mesh.IndexCount];
                        if (mesh.IndexType == 0x8000)
                        {
                            for (int f = 0; f < mesh.IndexCount; f++)
                            {
                                mesh.Faces[f] = reader.ReadByte();
                            }
                        }
                        else
                        {
                            for (int f = 0; f < mesh.IndexCount; f++)
                            {
                                mesh.Faces[f] = reader.ReadUInt16();
                            }
                        }

                        uint vertexStride = VertexLoaderExtension.GetStride(mesh.MeshHeader.VertexFormatHash);

                        for (int v = 0; v < mesh.MeshHeader.VertexCount; v++)
                        {
                            reader.SeekBegin(mesh.VertexBufferPointer + (v * vertexStride));
                            STVertex vertex = reader.ReadVertexLayout(mesh.MeshHeader.VertexFormatHash);

                            for (int j = 0; j < vertex.BoneIndices.Count; j++)
                            {
                                if (HashToBoneID.Count == 0)
                                {
                                    break;
                                }

                                uint boneHash = boneIDToHash[vertex.BoneIndices[j]];
                                //Get the index used from the skeleton's hash list
                                int boneIndex = HashToBoneID[boneHash];

                                vertex.BoneIndices[j] = boneIndex;
                            }


                            vertex.Position = Vector3.TransformPosition(vertex.Position, model.Transform);
                            //Transform 90 degrees and scale
                            vertex.Position = new Vector3(
                                vertex.Position.X,
                                vertex.Position.Z,
                                -vertex.Position.Y) * ModelWrapper.PreviewScale;
                            vertex.Normal = new Vector3(
                                vertex.Normal.X,
                                vertex.Normal.Z,
                                -vertex.Normal.Y);

                            mesh.Vertices.Add(vertex);
                        }

                        if (mesh.Vertices.Any(x => x.BoneIndices.Count > 0))
                        {
                            skinningIndex += 1;
                        }
                    }
                }
            }
        }
Ejemplo n.º 18
0
        public static List <ModelInfo> Read(List <ChunkTable.ChunkDataEntry> chunkList,
                                            Dictionary <uint, int> HashToBoneID)
        {
            List <ModelInfo> models        = new List <ModelInfo>();
            List <Header>    modelHeaders  = new List <Header>();
            List <MeshInfo>  meshes        = new List <MeshInfo>();
            List <Matrix4>   modelMatrices = new List <Matrix4>();

            var vertexPointerChunk = chunkList.FirstOrDefault(
                x => x.ChunkType == ChunkDataType.VertexStartPointers);

            var bufferChunk = chunkList.FirstOrDefault(
                x => x.ChunkType == ChunkDataType.MeshBuffers);

            for (int i = 0; i < chunkList.Count; i++)
            {
                var chunk = chunkList[i];
                switch (chunk.ChunkType)
                {
                case ChunkDataType.ModelInfo:
                    uint numModels = (uint)chunk.Data.Length / MODEL_HEADER_SIZE;
                    modelHeaders = chunk.ReadStructs <Header>(numModels);
                    break;

                case ChunkDataType.ModelTransform:
                    int numTransforms = (int)chunk.Data.Length / 64;
                    using (var reader = new FileReader(chunk.Data, true))
                    {
                        for (int j = 0; j < numTransforms; j++)
                        {
                            var values = reader.ReadSingles(16);
                            modelMatrices.Add(new Matrix4(
                                                  values[0], values[1], values[2], values[3],
                                                  values[4], values[5], values[6], values[7],
                                                  values[8], values[9], values[10], values[11],
                                                  values[12], values[13], values[14], values[15]));
                        }
                    }
                    break;

                case ChunkDataType.MeshInfo:
                    uint numMeshes   = (uint)chunk.Data.Length / MESH_SIZE;
                    var  meshHeaders = chunk.ReadStructs <Mesh>(numMeshes);
                    //Load mesh structs into mesh info
                    //This will store vertex and face data

                    //Read vertex points. These must be parsed by mesh header data
                    using (var reader = new FileReader(vertexPointerChunk.Data, true))
                    {
                        for (int m = 0; m < numMeshes; m++)
                        {
                            var mesh = new MeshInfo(meshHeaders[m]);
                            meshes.Add(mesh);

                            if (mesh.HasSkinning && reader.BaseStream.Length >= reader.Position + 4)
                            {
                                mesh.SkinningBufferPointer = reader.ReadUInt32();
                            }
                            if (reader.BaseStream.Length >= reader.Position + 4)
                            {
                                mesh.VertexBufferPointer = reader.ReadUInt32();
                            }
                            if (reader.BaseStream.Length >= reader.Position + 4)
                            {
                                reader.ReadUInt32();
                            }
                            if (reader.BaseStream.Length >= reader.Position + 4)
                            {
                                reader.ReadUInt32();
                            }
                        }
                    }
                    break;
                }
            }

            var materialChunk = chunkList.FirstOrDefault(
                x => x.ChunkType == ChunkDataType.MaterialData);

            var materialLookupChunk = chunkList.FirstOrDefault(
                x => x.ChunkType == ChunkDataType.MaterialLookupTable);

            MaterialLoaderHelper.ParseMaterials(materialChunk.Data, materialLookupChunk.Data, meshes);

            int meshIndex = 0;

            for (int i = 0; i < modelHeaders.Count; i++)
            {
                var model = new ModelInfo()
                {
                    Hash = modelHeaders[i].Hash
                };
                models.Add(model);

                if (modelMatrices.Count > i)
                {
                    model.Transform = modelMatrices[i];
                }

                for (int j = 0; j < modelHeaders[i].MeshCount; j++)
                {
                    model.Meshes.Add(meshes[meshIndex + j]);
                }

                meshIndex += (int)modelHeaders[i].MeshCount;
            }

            //Get our bone hash index lists
            Dictionary <int, uint> boneIDToHash = new Dictionary <int, uint>();

            var boneStart = chunkList.FirstOrDefault(
                x => x.ChunkType == ChunkDataType.BoneStart);

            var boneHashChunk = boneStart != null?boneStart.SubData.FirstOrDefault(
                x => x.ChunkType == ChunkDataType.BoneHashList) : null;

            if (boneHashChunk != null)
            {
                uint count  = (uint)boneHashChunk.Data.Length / 4;
                var  hashes = boneHashChunk.ReadPrimitive <uint>(count);
                for (int i = 0; i < count; i++)
                {
                    boneIDToHash.Add(i, hashes[i]);
                }
            }

            //Lastly parse the vertex and index buffers
            using (var reader = new FileReader(bufferChunk.Data, true)) {
                foreach (var model in models)
                {
                    foreach (var mesh in model.Meshes)
                    {
                        reader.SeekBegin(mesh.MeshHeader.IndexOffset);

                        mesh.Faces = new uint[mesh.IndexCount];
                        if (mesh.IndexType == 0x80)
                        {
                            for (int f = 0; f < mesh.IndexCount; f++)
                            {
                                mesh.Faces[f] = reader.ReadByte();
                            }
                        }
                        else if (mesh.IndexType == 0x40)
                        {
                            for (int f = 0; f < mesh.IndexCount; f++)
                            {
                                mesh.Faces[f] = reader.ReadUInt32();
                            }
                        }
                        else
                        {
                            for (int f = 0; f < mesh.IndexCount; f++)
                            {
                                mesh.Faces[f] = reader.ReadUInt16();
                            }
                        }

                        reader.SeekBegin(mesh.VertexBufferPointer);
                        for (int v = 0; v < mesh.MeshHeader.VertexCount; v++)
                        {
                            STVertex vertex = new STVertex();
                            vertex.Position = reader.ReadVec3();
                            float texCoordU = reader.ReadSingle();
                            vertex.Normal = reader.ReadVec3();
                            float texCoordV = reader.ReadSingle();
                            vertex.Tangent = reader.ReadVec4();

                            vertex.TexCoords = new Vector2[1]
                            {
                                new Vector2(texCoordU, texCoordV)
                            };

                            vertex.Position = Vector3.TransformPosition(vertex.Position, model.Transform);

                            //Transform 90 degrees and scale
                            vertex.Position = new Vector3(
                                vertex.Position.X,
                                vertex.Position.Z,
                                -vertex.Position.Y) * ModelWrapper.PreviewScale;
                            vertex.Normal = new Vector3(
                                vertex.Normal.X,
                                vertex.Normal.Z,
                                -vertex.Normal.Y);

                            mesh.Vertices.Add(vertex);
                        }

                        if (mesh.HasSkinning && HashToBoneID.Count > 0)
                        {
                            reader.SeekBegin(mesh.SkinningBufferPointer);
                            for (int v = 0; v < mesh.MeshHeader.VertexCount; v++)
                            {
                                byte[]  boneIndices = reader.ReadBytes(4);
                                float[] weights     = reader.ReadSingles(4);

                                for (int j = 0; j < 4; j++)
                                {
                                    if (weights[j] == 0)
                                    {
                                        break;
                                    }

                                    //Get the hash indexing the model's bone hash list
                                    uint boneHash = boneIDToHash[boneIndices[j]];
                                    //Get the index used from the skeleton's hash list
                                    int boneIndex = HashToBoneID[boneHash];

                                    mesh.Vertices[v].BoneIndices.Add(boneIndex);
                                    mesh.Vertices[v].BoneWeights.Add(weights[j]);
                                }
                            }
                        }
                    }
                }
            }
            return(models);
        }