// Taken from: http://answers.unity3d.com/comments/190515/view.html
        // Official support for Mesh.RecalculateTangents should be coming in 5.6
        // https://feedback.unity3d.com/suggestions/recalculatetangents

        /*private MeshPrimitiveAttributes CalculateAndSetTangents(MeshPrimitiveAttributes attributes)
         * {
         *      var triangleCount = attributes.Triangles.Length;
         *      var vertexCount = attributes.Vertices.Length;
         *
         *      var tan1 = new Vector3[vertexCount];
         *      var tan2 = new Vector3[vertexCount];
         *
         *      attributes.Tangents = new Vector4[vertexCount];
         *
         *      for (long a = 0; a < triangleCount; a += 3)
         *      {
         *              long i1 = attributes.Triangles[a + 0];
         *              long i2 = attributes.Triangles[a + 1];
         *              long i3 = attributes.Triangles[a + 2];
         *
         *              var v1 = attributes.Vertices[i1];
         *              var v2 = attributes.Vertices[i2];
         *              var v3 = attributes.Vertices[i3];
         *
         *              var w1 = attributes.Uv[i1];
         *              var w2 = attributes.Uv[i2];
         *              var w3 = attributes.Uv[i3];
         *
         *              var x1 = v2.X - v1.X;
         *              var x2 = v3.X - v1.X;
         *              var y1 = v2.Y - v1.Y;
         *              var y2 = v3.Y - v1.Y;
         *              var z1 = v2.Z - v1.Z;
         *              var z2 = v3.Z - v1.Z;
         *
         *              var s1 = w2.X - w1.X;
         *              var s2 = w3.X - w1.X;
         *              var t1 = w2.Y - w1.Y;
         *              var t2 = w3.Y - w1.Y;
         *
         *              var r = 1.0f / (s1 * t2 - s2 * t1);
         *
         *              var sdir = new Vector3((t2 * x1 - t1 * x2) * r, (t2 * y1 - t1 * y2) * r, (t2 * z1 - t1 * z2) * r);
         *              var tdir = new Vector3((s1 * x2 - s2 * x1) * r, (s1 * y2 - s2 * y1) * r, (s1 * z2 - s2 * z1) * r);
         *
         *              tan1[i1] += sdir;
         *              tan1[i2] += sdir;
         *              tan1[i3] += sdir;
         *
         *              tan2[i1] += tdir;
         *              tan2[i2] += tdir;
         *              tan2[i3] += tdir;
         *      }
         *
         *
         *      for (long a = 0; a < vertexCount; ++a)
         *      {
         *              var n = attributes.Normals[a];
         *              var t = tan1[a];
         *
         *              Vector3.OrthoNormalize(ref n, ref t);
         *
         *              attributes.Tangents[a].X = t.X;
         *              attributes.Tangents[a].Y = t.Y;
         *              attributes.Tangents[a].Z = t.Z;
         *
         *              attributes.Tangents[a].W = (Vector3.Dot(Vector3.Cross(n, t), tan2[a]) < 0.0f) ? -1.0f : 1.0f;
         *      }
         *
         *      return attributes;
         * }*/

        public static MeshPrimitive Deserialize(GLTFRoot root, JsonReader reader)
        {
            var primitive = new MeshPrimitive();

            while (reader.Read() && reader.TokenType == JsonToken.PropertyName)
            {
                var curProp = reader.Value.ToString();

                switch (curProp)
                {
                case "attributes":
                    primitive.Attributes = reader.ReadAsDictionary(() => new AccessorId
                    {
                        Id   = reader.ReadAsInt32().Value,
                        Root = root
                    });
                    break;

                case "indices":
                    primitive.Indices = AccessorId.Deserialize(root, reader);
                    break;

                case "material":
                    primitive.Material = MaterialId.Deserialize(root, reader);
                    break;

                case "mode":
                    primitive.Mode = (DrawMode)reader.ReadAsInt32().Value;
                    break;

                case "targets":
                    primitive.Targets = reader.ReadList(() =>
                    {
                        return(reader.ReadAsDictionary(() => new AccessorId
                        {
                            Id = reader.ReadAsInt32().Value,
                            Root = root
                        },
                                                       skipStartObjectRead: true));
                    });
                    break;

                default:
                    primitive.DefaultPropertyDeserializer(root, reader);
                    break;
                }
            }

            return(primitive);
        }
Example #2
0
        // Taken from: http://answers.unity3d.com/comments/190515/view.html
        // Official support for Mesh.RecalculateTangents should be coming in 5.6
        // https://feedback.unity3d.com/suggestions/recalculatetangents

        /*private MeshPrimitiveAttributes CalculateAndSetTangents(MeshPrimitiveAttributes attributes)
         * {
         *      var triangleCount = attributes.Triangles.Length;
         *      var vertexCount = attributes.Vertices.Length;
         *
         *      var tan1 = new Vector3[vertexCount];
         *      var tan2 = new Vector3[vertexCount];
         *
         *      attributes.Tangents = new Vector4[vertexCount];
         *
         *      for (long a = 0; a < triangleCount; a += 3)
         *      {
         *              long i1 = attributes.Triangles[a + 0];
         *              long i2 = attributes.Triangles[a + 1];
         *              long i3 = attributes.Triangles[a + 2];
         *
         *              var v1 = attributes.Vertices[i1];
         *              var v2 = attributes.Vertices[i2];
         *              var v3 = attributes.Vertices[i3];
         *
         *              var w1 = attributes.Uv[i1];
         *              var w2 = attributes.Uv[i2];
         *              var w3 = attributes.Uv[i3];
         *
         *              var x1 = v2.X - v1.X;
         *              var x2 = v3.X - v1.X;
         *              var y1 = v2.Y - v1.Y;
         *              var y2 = v3.Y - v1.Y;
         *              var z1 = v2.Z - v1.Z;
         *              var z2 = v3.Z - v1.Z;
         *
         *              var s1 = w2.X - w1.X;
         *              var s2 = w3.X - w1.X;
         *              var t1 = w2.Y - w1.Y;
         *              var t2 = w3.Y - w1.Y;
         *
         *              var r = 1.0f / (s1 * t2 - s2 * t1);
         *
         *              var sdir = new Vector3((t2 * x1 - t1 * x2) * r, (t2 * y1 - t1 * y2) * r, (t2 * z1 - t1 * z2) * r);
         *              var tdir = new Vector3((s1 * x2 - s2 * x1) * r, (s1 * y2 - s2 * y1) * r, (s1 * z2 - s2 * z1) * r);
         *
         *              tan1[i1] += sdir;
         *              tan1[i2] += sdir;
         *              tan1[i3] += sdir;
         *
         *              tan2[i1] += tdir;
         *              tan2[i2] += tdir;
         *              tan2[i3] += tdir;
         *      }
         *
         *
         *      for (long a = 0; a < vertexCount; ++a)
         *      {
         *              var n = attributes.Normals[a];
         *              var t = tan1[a];
         *
         *              Vector3.OrthoNormalize(ref n, ref t);
         *
         *              attributes.Tangents[a].X = t.X;
         *              attributes.Tangents[a].Y = t.Y;
         *              attributes.Tangents[a].Z = t.Z;
         *
         *              attributes.Tangents[a].W = (Vector3.Dot(Vector3.Cross(n, t), tan2[a]) < 0.0f) ? -1.0f : 1.0f;
         *      }
         *
         *      return attributes;
         * }*/

        public static MeshPrimitive Deserialize(GLTFRoot root, JsonReader reader)
        {
            var primitive = new MeshPrimitive();

            while (reader.Read() && reader.TokenType == JsonToken.PropertyName)
            {
                var curProp = reader.Value.ToString();

                switch (curProp)
                {
                case "attributes":
                    primitive.Attributes = reader.ReadAsDictionary(() => new AccessorId
                    {
                        Id   = reader.ReadAsInt32().Value,
                        Root = root
                    });
                    break;

                case "indices":
                    primitive.Indices = AccessorId.Deserialize(root, reader);
                    break;

                case "material":
                    primitive.Material = MaterialId.Deserialize(root, reader);
                    break;

                case "mode":
                    primitive.Mode = (DrawMode)reader.ReadAsInt32().Value;
                    break;

                case "targets":
                    primitive.Targets = reader.ReadList(() =>
                    {
                        return(reader.ReadAsDictionary(() => new AccessorId
                        {
                            Id = reader.ReadAsInt32().Value,
                            Root = root
                        },
                                                       skipStartObjectRead: true));
                    });
                    break;

                case "extras":
                    // GLTF does not support morph target names, serialize in extras for now
                    // https://github.com/KhronosGroup/glTF/issues/1036
                    if (reader.Read() && reader.TokenType == JsonToken.StartObject)
                    {
                        while (reader.Read() && reader.TokenType == JsonToken.PropertyName)
                        {
                            var extraProperty = reader.Value.ToString();
                            switch (extraProperty)
                            {
                            case "targetNames":
                                primitive.TargetNames = reader.ReadStringList();
                                break;
                            }
                        }
                    }

                    break;

                default:
                    primitive.DefaultPropertyDeserializer(root, reader);
                    break;
                }
            }

            return(primitive);
        }