Пример #1
0
        // https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#meshes

        int ExportIndices(int[] indices)
        {
            // https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#primitiveindices

            indices = CoordUtils.FlipIndices(indices).ToArray();

            // Scalar | UNSIGNED_BYTE
            //        | UNSIGNED_SHORT
            //        | UNSIGNED_INT! (TODO: optimize kind...)

            byte[] buffer    = PrimitiveExporter.Marshal(indices);
            var    viewIndex = BufferBuilder.AddView(
                new ArraySegment <byte>(buffer),
                null,
                Types.BufferView.TargetEnum.ELEMENT_ARRAY_BUFFER);

            var viewComponentType = Types.Accessor.ComponentTypeEnum.UNSIGNED_INT;

            var accessor = new Types.Accessor
            {
                BufferView    = viewIndex,
                ByteOffset    = 0,
                ComponentType = viewComponentType,
                Count         = indices.Length,
                Type          = Types.Accessor.TypeEnum.Scalar,
            };

            return(Types.GltfExtensions.AddAccessor(Gltf, accessor));
        }
Пример #2
0
        IndexedResource <Skin> ForceExportSkin(SkinnedMeshRenderer smr, Mesh mesh)
        {
            var rootBone    = smr.rootBone != null ? (int?)Export(smr.rootBone).Index : null;
            var boneIndices = smr.bones.Select(bt => Export(bt).Index).ToArray();

            var primitiveExporter = new PrimitiveExporter(this);

            int?matricesAccIndex = null;

            if (mesh.bindposes.Length > 0)
            {
                matricesAccIndex = ExportInverseBindMatrices(mesh.bindposes);
            }

            var gltfSkin = new Types.Skin
            {
                InverseBindMatrices = matricesAccIndex,
                Skeleton            = rootBone,
                Joints = boneIndices,
            };

            return(new IndexedResource <Skin> {
                Index = Types.GltfExtensions.AddSkin(Gltf, gltfSkin),
                Value = new Skin(),
            });
        }
Пример #3
0
        int ExportPositionsBuffer(ref Vector3[] vec3, out Types.Accessor.ComponentTypeEnum componentType)
        {
            vec3 = vec3.Select(CoordUtils.ConvertSpace).ToArray();

            // VEC3! | FLOAT!
            byte[] buffer    = PrimitiveExporter.Marshal(vec3);
            var    viewIndex = BufferBuilder.AddView(new ArraySegment <byte>(buffer));

            componentType = Types.Accessor.ComponentTypeEnum.FLOAT;

            return(viewIndex);
        }
Пример #4
0
        int ExportSparseIndicesBuffer(ref int[] indices, out Types.Accessor.SparseType.IndicesType.ComponentTypeEnum componentType)
        {
            // Scalar | UNSIGNED_BYTE
            //        | UNSIGNED_SHORT
            //        | UNSIGNED_INT! (TODO: optimize kind...)
            byte[] buffer    = PrimitiveExporter.Marshal(indices);
            var    viewIndex = BufferBuilder.AddView(new ArraySegment <byte>(buffer));

            componentType = Types.Accessor.SparseType.IndicesType.ComponentTypeEnum.UNSIGNED_INT;

            return(viewIndex);
        }
Пример #5
0
        // https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#skin

        int ExportInverseBindMatrices(Matrix4x4[] matrices)
        {
            matrices = matrices.Select(CoordUtils.ConvertSpace).ToArray();

            // MAT4! | FLOAT!
            byte[] buffer    = PrimitiveExporter.Marshal(matrices);
            var    viewIndex = BufferBuilder.AddView(new ArraySegment <byte>(buffer));

            var accessor = new Types.Accessor
            {
                BufferView    = viewIndex,
                ByteOffset    = 0,
                ComponentType = Types.Accessor.ComponentTypeEnum.FLOAT,
                Count         = matrices.Length,
                Type          = Types.Accessor.TypeEnum.Mat4,
            };

            return(Types.GltfExtensions.AddAccessor(Gltf, accessor));
        }
Пример #6
0
        int ExportWeights(Vector4[] weights)
        {
            // VEC4! | FLOAT!
            //       | UNSIGNED_BYTE  (normalized)
            //       | UNSIGNED_SHORT (normalized)
            byte[] buffer    = PrimitiveExporter.Marshal(weights);
            var    viewIndex = BufferBuilder.AddView(new ArraySegment <byte>(buffer));

            var accessor = new Types.Accessor
            {
                BufferView    = viewIndex,
                ByteOffset    = 0,
                ComponentType = Types.Accessor.ComponentTypeEnum.FLOAT,
                Count         = weights.Length,
                Type          = Types.Accessor.TypeEnum.Vec4,
            };

            return(Types.GltfExtensions.AddAccessor(Gltf, accessor));
        }
Пример #7
0
        int ExportTangents(Vector4[] vec4)
        {
            vec4 = vec4.Select(CoordUtils.ConvertSpace).ToArray();

            // VEC4! | FLOAT!
            byte[] buffer    = PrimitiveExporter.Marshal(vec4);
            var    viewIndex = BufferBuilder.AddView(new ArraySegment <byte>(buffer));

            var accessor = new Types.Accessor
            {
                BufferView    = viewIndex,
                ByteOffset    = 0,
                ComponentType = Types.Accessor.ComponentTypeEnum.FLOAT,
                Count         = vec4.Length,
                Type          = Types.Accessor.TypeEnum.Vec4,
            };

            return(Types.GltfExtensions.AddAccessor(Gltf, accessor));
        }
Пример #8
0
        int ExportUV(Vector2[] uv)
        {
            uv = uv.Select(CoordUtils.ConvertUV).ToArray();

            // VEC2! | FLOAT!
            //       | UNSIGNED_BYTE  (normalized)
            //       | UNSIGNED_SHORT (normalized)
            byte[] buffer    = PrimitiveExporter.Marshal(uv);
            var    viewIndex = BufferBuilder.AddView(new ArraySegment <byte>(buffer));

            var accessor = new Types.Accessor
            {
                BufferView    = viewIndex,
                ByteOffset    = 0,
                ComponentType = Types.Accessor.ComponentTypeEnum.FLOAT,
                Count         = uv.Length,
                Type          = Types.Accessor.TypeEnum.Vec2,
            };

            return(Types.GltfExtensions.AddAccessor(Gltf, accessor));
        }
Пример #9
0
        int ExportJoints(Vec4 <int>[] joints)
        {
            // VEC4! | UNSIGNED_BYTE
            //       | UNSIGNED_SHORT!
            byte[] buffer = PrimitiveExporter.Marshal(
                joints
                .Select(v => new Vec4 <ushort>((ushort)v.x, (ushort)v.y, (ushort)v.z, (ushort)v.w))
                .ToArray()
                );
            var viewIndex = BufferBuilder.AddView(new ArraySegment <byte>(buffer));

            var accessor = new Types.Accessor
            {
                BufferView    = viewIndex,
                ByteOffset    = 0,
                ComponentType = Types.Accessor.ComponentTypeEnum.UNSIGNED_SHORT,
                Count         = joints.Length,
                Type          = Types.Accessor.TypeEnum.Vec4,
            };

            return(Types.GltfExtensions.AddAccessor(Gltf, accessor));
        }
Пример #10
0
        public IndexedResource <Mesh> ForceExport(Renderer r, Mesh mesh)
        {
            var materialIndices = new List <int>();

            foreach (var m in r.sharedMaterials)
            {
                var materialResource = Materials.Export(m);
                materialIndices.Add(materialResource.Index);
            }

            var primitiveExporter = new PrimitiveExporter(this);

            // Convert to right-handed coordinate system
            var positionAccIndex = ExportPositions(mesh.vertices);

            int?normalAccIndex = null;

            if (mesh.normals.Length > 0)
            {
                normalAccIndex = ExportNormals(mesh.normals);
            }

            int?tangentAccIndex = null;
            //if (mesh.tangents.Length > 0)
            //{
            //    tangentAccIndex = ExportTangents(mesh.tangents);
            //}

            int?texcoord0AccIndex = null;

            if (mesh.uv.Length > 0)
            {
                texcoord0AccIndex = ExportUV(mesh.uv);
            }

            int?texcoord1AccIndex = null;

            if (mesh.uv2.Length > 0)
            {
                texcoord1AccIndex = ExportUV(mesh.uv2);
            }

            int?color0AccIndex = null;

            if (mesh.colors.Length > 0)
            {
                color0AccIndex = ExportColors(mesh.colors);
            }

            int?joints0AccIndex  = null;
            int?weights0AccIndex = null;

            if (mesh.boneWeights.Length > 0)
            {
                var joints = mesh.boneWeights
                             .Select(w => new Vec4 <int>(
                                         w.boneIndex0,
                                         w.boneIndex1,
                                         w.boneIndex2,
                                         w.boneIndex3)
                                     ).ToArray();
                var weights = mesh.boneWeights
                              .Select(w => new Vector4(
                                          w.weight0,
                                          w.weight1,
                                          w.weight2,
                                          w.weight3)
                                      ).ToArray();

                joints0AccIndex  = ExportJoints(joints);
                weights0AccIndex = ExportWeights(weights);
            }

            #region blendSpace
            List <Target> targets = null;
            if (mesh.blendShapeCount > 0)
            {
                targets = new List <Target>();

                for (int i = 0; i < mesh.blendShapeCount; ++i)
                {
                    var name = mesh.GetBlendShapeName(i);

                    var deltaVertices = new Vector3[mesh.vertexCount];
                    var deltaNormals  = new Vector3[mesh.vertexCount];
                    var deltaTangents = new Vector3[mesh.vertexCount];

                    var frameCount = mesh.GetBlendShapeFrameCount(i);
                    mesh.GetBlendShapeFrameVertices(
                        i,
                        frameCount - 1 /* get last frame */,
                        deltaVertices,
                        deltaNormals,
                        deltaTangents);

                    // TODO: Export as sparse accessors
                    var mPositionAccIndex = ExportPositions(deltaVertices);
                    var mNormalsAccIndex  = ExportNormals(deltaNormals);
                    //var mTangentsAccIndex = ExportPositions(deltaTangents);
                    var mTangentsAccIndex = (int?)null;

                    var weight = mesh.GetBlendShapeFrameWeight(
                        i,
                        frameCount - 1 /* get last frame */);

                    targets.Add(new Target
                    {
                        Name = name,

                        Position = mPositionAccIndex,
                        Normal   = mNormalsAccIndex,
                        Tangent  = mTangentsAccIndex,

                        Weight = weight,
                    });
                }
            }

            List <Dictionary <string, int> > primTargets = null;
            if (targets != null)
            {
                primTargets = new List <Dictionary <string, int> >();

                foreach (var t in targets)
                {
                    var primTarget = new Dictionary <string, int>();
                    primTarget[TMPA.POSITION] = t.Position;
                    if (t.Normal != null)
                    {
                        primTarget[TMPA.NORMAL] = t.Normal.Value;
                    }
                    if (t.Tangent != null)
                    {
                        primTarget[TMPA.TANGENT] = t.Tangent.Value;
                    }

                    primTargets.Add(primTarget);
                }
            }
            #endregion

            var primitives = new List <Types.Mesh.PrimitiveType>();
            for (var i = 0; i < mesh.subMeshCount; ++i)
            {
                var indices = mesh.GetIndices(i);
                var positionindicesAccIndex = ExportIndices(indices);

                var attrs = new Dictionary <string, int>();
                attrs[TMPA.POSITION] = positionAccIndex;
                if (normalAccIndex != null)
                {
                    attrs[TMPA.NORMAL] = normalAccIndex.Value;
                }
                if (tangentAccIndex != null)
                {
                    attrs[TMPA.TANGENT] = tangentAccIndex.Value;
                }
                if (texcoord0AccIndex != null)
                {
                    attrs[TMPA.TEXCOORD_0] = texcoord0AccIndex.Value;
                }
                if (texcoord1AccIndex != null)
                {
                    attrs[TMPA.TEXCOORD_1] = texcoord1AccIndex.Value;
                }
                if (color0AccIndex != null)
                {
                    attrs[TMPA.COLOR_0] = color0AccIndex.Value;
                }
                if (joints0AccIndex != null)
                {
                    attrs[TMPA.JOINTS_0] = joints0AccIndex.Value;
                }
                if (weights0AccIndex != null)
                {
                    attrs[TMPA.WEIGHTS_0] = weights0AccIndex.Value;
                }

                var primitive = new Types.Mesh.PrimitiveType
                {
                    Attributes = attrs,
                    Indices    = positionindicesAccIndex,
                    Material   = materialIndices[i < materialIndices.Count ? i : materialIndices.Count - 1],
                    Targets    = primTargets,
                };
                primitives.Add(primitive);
            }

            var gltfMesh = new Types.Mesh
            {
                Name = mesh.name,

                Primitives = primitives,
                // Weights = Should support default morph target weights?
            };
            if (targets != null)
            {
                var targetNames = targets.Select(t => t.Name).ToArray();

                // https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#morph-targets
                gltfMesh.Extras = new Dictionary <string, object>
                {
                    { "targetNames", targetNames },
                };
            }

            return(new IndexedResource <Mesh>
            {
                Index = Types.GltfExtensions.AddMesh(Gltf, gltfMesh),
                Value = mesh,
            });
        }