// -----------------------------------------
        // DumpAnims
        // -----------------------------------------

        void DumpAnims(GameObject _animPrefab, GLTF _gltf, BufferInfo _bufInfo)
        {
            // get animations
            GameObject           prefabInst = PrefabUtility.InstantiatePrefab(_animPrefab) as GameObject;
            List <AnimationClip> clips      = Utils.GetAnimationClips(prefabInst);

            // get joints
            List <GameObject> joints = new List <GameObject>();

            Utils.RecurseNode(prefabInst, _go => {
                // this is not a joint
                if (_go.GetComponent <SkinnedMeshRenderer>() != null)
                {
                    return(false);
                }

                joints.Add(_go);
                return(true);
            });

            //
            if (clips != null)
            {
                // process AnimationClip(s)
                foreach (AnimationClip clip in clips)
                {
                    int accOffset = _bufInfo.GetAccessorCount();

                    AnimData animData = DumpAnimData(prefabInst, clip);
                    DumpBufferInfoFromAnimData(animData, _bufInfo);

                    GLTF_AnimationEx gltfAnim = DumpGltfAnimationEx(animData, joints, accOffset);
                    _gltf.animations.Add(gltfAnim);
                }
            }

            Object.DestroyImmediate(prefabInst);
        }
Exemple #2
0
        // -----------------------------------------
        // DumpBufferInfoFromMesh
        // -----------------------------------------

        void DumpBufferInfoFromMesh(Mesh _mesh, BufferInfo _bufInfo)
        {
            int vertexBytes = 0;

            byte[]        vertexData;
            List <byte[]> indexDataList = new List <byte[]>();

            byte[]       bindposesData;
            Vector3[]    vertices      = _mesh.vertices;
            Vector3[]    normals       = _mesh.normals;
            Vector4[]    tangents      = _mesh.tangents;
            Color[]      colors        = _mesh.colors;
            Vector2[]    uv            = _mesh.uv;
            Vector2[]    uv2           = _mesh.uv2;
            Vector2[]    uv3           = _mesh.uv3;
            Vector2[]    uv4           = _mesh.uv4;
            BoneWeight[] boneWeights   = _mesh.boneWeights;
            int          offsetNormal  = 0;
            int          offsetTangent = 0;
            int          offsetColor   = 0;
            int          offsetUV      = 0;
            int          offsetUV2     = 0;
            int          offsetUV3     = 0;
            int          offsetUV4     = 0;
            int          offsetJoint   = 0;
            int          offsetWeight  = 0;
            int          offsetBuffer  = _bufInfo.data.Length;
            Vector3      minPos        = Vector3.zero;
            Vector3      maxPos        = Vector3.zero;
            Vector3      minNormal     = Vector3.zero;
            Vector3      maxNormal     = Vector3.zero;
            Vector4      minTangent    = Vector4.zero;
            Vector4      maxTangent    = Vector4.zero;

            if (vertices.Length > 0)
            {
                minPos       = maxPos = vertices[0];
                vertexBytes += 12; // float32 * 3
            }

            if (normals.Length > 0)
            {
                offsetNormal = vertexBytes;
                vertexBytes += 12; // float32 * 3
            }

            if (tangents.Length > 0)
            {
                offsetTangent = vertexBytes;
                vertexBytes  += 16; // float32 * 4
            }

            if (colors.Length > 0)
            {
                offsetColor  = vertexBytes;
                vertexBytes += 16; // float32 * 4
            }

            if (uv.Length > 0)
            {
                offsetUV     = vertexBytes;
                vertexBytes += 8; // float32 * 2
            }

            if (uv2.Length > 0)
            {
                offsetUV2    = vertexBytes;
                vertexBytes += 8; // float32 * 2
            }

            if (uv3.Length > 0)
            {
                offsetUV3    = vertexBytes;
                vertexBytes += 8; // float32 * 2
            }

            if (uv4.Length > 0)
            {
                offsetUV4    = vertexBytes;
                vertexBytes += 8; // float32 * 2
            }

            if (boneWeights.Length > 0)
            {
                offsetJoint  = vertexBytes;
                vertexBytes += 8; // uint16 * 4

                offsetWeight = vertexBytes;
                vertexBytes += 16; // float32 * 4
            }

            // vertexData
            using (MemoryStream stream = new MemoryStream(vertexBytes * _mesh.vertexCount)) {
                using (BinaryWriter writer = new BinaryWriter(stream)) {
                    for (int i = 0; i < _mesh.vertexCount; ++i)
                    {
                        if (vertices.Length > 0)
                        {
                            Vector3 vert = vertices[i];
                            // NOTE: convert LH to RH
                            vert.z = -vert.z;

                            writer.Write(vert.x);
                            writer.Write(vert.y);
                            writer.Write(vert.z);

                            if (vert.x < minPos.x)
                            {
                                minPos.x = vert.x;
                            }
                            if (vert.y < minPos.y)
                            {
                                minPos.y = vert.y;
                            }
                            if (vert.z < minPos.z)
                            {
                                minPos.z = vert.z;
                            }
                            if (vert.x > maxPos.x)
                            {
                                maxPos.x = vert.x;
                            }
                            if (vert.y > maxPos.y)
                            {
                                maxPos.y = vert.y;
                            }
                            if (vert.z > maxPos.z)
                            {
                                maxPos.z = vert.z;
                            }
                        }

                        if (normals.Length > 0)
                        {
                            Vector3 normal = normals[i];
                            // NOTE: convert LH to RH
                            normal.z = -normal.z;

                            writer.Write(normal.x);
                            writer.Write(normal.y);
                            writer.Write(normal.z);

                            if (normal.x < minNormal.x)
                            {
                                minNormal.x = normal.x;
                            }
                            if (normal.y < minNormal.y)
                            {
                                minNormal.y = normal.y;
                            }
                            if (normal.z < minNormal.z)
                            {
                                minNormal.z = normal.z;
                            }
                            if (normal.x > maxNormal.x)
                            {
                                maxNormal.x = normal.x;
                            }
                            if (normal.y > maxNormal.y)
                            {
                                maxNormal.y = normal.y;
                            }
                            if (normal.z > maxNormal.z)
                            {
                                maxNormal.z = normal.z;
                            }
                        }

                        if (tangents.Length > 0)
                        {
                            Vector4 tangent = tangents[i];
                            // NOTE: convert LH to RH
                            tangent.z = -tangent.z;

                            writer.Write(tangent.x);
                            writer.Write(tangent.y);
                            writer.Write(tangent.z);
                            writer.Write(tangent.w);

                            if (tangent.x < minTangent.x)
                            {
                                minTangent.x = tangent.x;
                            }
                            if (tangent.y < minTangent.y)
                            {
                                minTangent.y = tangent.y;
                            }
                            if (tangent.z < minTangent.z)
                            {
                                minTangent.z = tangent.z;
                            }
                            if (tangent.w < minTangent.w)
                            {
                                minTangent.w = tangent.w;
                            }
                            if (tangent.x > maxTangent.x)
                            {
                                maxTangent.x = tangent.x;
                            }
                            if (tangent.y > maxTangent.y)
                            {
                                maxTangent.y = tangent.y;
                            }
                            if (tangent.z > maxTangent.z)
                            {
                                maxTangent.z = tangent.z;
                            }
                            if (tangent.w > maxTangent.w)
                            {
                                maxTangent.w = tangent.w;
                            }
                        }

                        if (colors.Length > 0)
                        {
                            writer.Write(colors[i].r);
                            writer.Write(colors[i].g);
                            writer.Write(colors[i].b);
                            writer.Write(colors[i].a);
                        }

                        if (uv.Length > 0)
                        {
                            writer.Write(uv[i].x);
                            writer.Write(uv[i].y);
                        }

                        if (uv2.Length > 0)
                        {
                            writer.Write(uv2[i].x);
                            writer.Write(uv2[i].y);
                        }

                        if (uv3.Length > 0)
                        {
                            writer.Write(uv3[i].x);
                            writer.Write(uv3[i].y);
                        }

                        if (uv4.Length > 0)
                        {
                            writer.Write(uv4[i].x);
                            writer.Write(uv4[i].y);
                        }

                        if (boneWeights.Length > 0)
                        {
                            writer.Write((ushort)boneWeights[i].boneIndex0);
                            writer.Write((ushort)boneWeights[i].boneIndex1);
                            writer.Write((ushort)boneWeights[i].boneIndex2);
                            writer.Write((ushort)boneWeights[i].boneIndex3);

                            writer.Write(boneWeights[i].weight0);
                            writer.Write(boneWeights[i].weight1);
                            writer.Write(boneWeights[i].weight2);
                            writer.Write(boneWeights[i].weight3);
                        }
                    }
                }
                vertexData = stream.ToArray();
            }

            // indexDataList
            for (int i = 0; i < _mesh.subMeshCount; ++i)
            {
                int[] subTriangles = _mesh.GetTriangles(i);

                if (subTriangles.Length > 0)
                {
                    using (MemoryStream stream = new MemoryStream(2 * subTriangles.Length)) {
                        using (BinaryWriter writer = new BinaryWriter(stream)) {
                            // DISABLE
                            // for ( int ii = 0; ii < subTriangles.Length; ++ii ) {
                            //   writer.Write((ushort)subTriangles[ii]);
                            // }

                            // NOTE: convert mesh winding order from CW (Unity3D's) to CCW (most webgl programs)
                            for (int ii = 0; ii < subTriangles.Length / 3; ++ii)
                            {
                                writer.Write((ushort)subTriangles[3 * ii]);
                                writer.Write((ushort)subTriangles[3 * ii + 2]);
                                writer.Write((ushort)subTriangles[3 * ii + 1]);
                            }
                        }

                        indexDataList.Add(stream.ToArray());
                    }
                }
            }

            // bindposesData
            using (MemoryStream stream = new MemoryStream(4 * 16 * _mesh.bindposes.Length)) {
                using (BinaryWriter writer = new BinaryWriter(stream)) {
                    for (int i = 0; i < _mesh.bindposes.Length; ++i)
                    {
                        Matrix4x4 bindpose = _mesh.bindposes[i];

                        // NOTE: convert LH to RH
                        writer.Write(bindpose[0]);
                        writer.Write(bindpose[1]);
                        writer.Write(-bindpose[2]); // a02
                        writer.Write(bindpose[3]);
                        writer.Write(bindpose[4]);
                        writer.Write(bindpose[5]);
                        writer.Write(-bindpose[6]); // a12
                        writer.Write(bindpose[7]);
                        writer.Write(-bindpose[8]); // a20
                        writer.Write(-bindpose[9]); // a21
                        writer.Write(bindpose[10]);
                        writer.Write(bindpose[11]);
                        writer.Write(bindpose[12]);
                        writer.Write(bindpose[13]);
                        writer.Write(-bindpose[14]); // b2
                        writer.Write(bindpose[15]);
                    }
                }
                bindposesData = stream.ToArray();
            }

            // bufferViews
            List <BufferViewInfo> bufferViews = new List <BufferViewInfo>();

            // vbView
            BufferViewInfo vbView = new BufferViewInfo
            {
                name      = "vb@" + _mesh.name,
                offset    = offsetBuffer,
                length    = vertexData.Length,
                stride    = vertexBytes,
                type      = BufferType.VERTEX,
                accessors = new List <AccessorInfo>(),
            };

            if (vertices.Length > 0)
            {
                AccessorInfo acc = new AccessorInfo
                {
                    name     = "position@" + _mesh.name,
                    offset   = 0,
                    count    = _mesh.vertexCount,
                    compType = ComponentType.FLOAT32,
                    attrType = AttrType.VEC3,
                    min      = new object[3] {
                        minPos.x, minPos.y, minPos.z
                    },
                    max = new object[3] {
                        maxPos.x, maxPos.y, maxPos.z
                    },
                };

                vbView.accessors.Add(acc);
            }

            if (normals.Length > 0)
            {
                AccessorInfo acc = new AccessorInfo
                {
                    name     = "normal@" + _mesh.name,
                    offset   = offsetNormal,
                    count    = _mesh.vertexCount,
                    compType = ComponentType.FLOAT32,
                    attrType = AttrType.VEC3,
                    min      = new object[3] {
                        minNormal.x, minNormal.y, minNormal.z
                    },
                    max = new object[3] {
                        maxNormal.x, maxNormal.y, maxNormal.z
                    },
                };

                vbView.accessors.Add(acc);
            }

            if (tangents.Length > 0)
            {
                AccessorInfo acc = new AccessorInfo
                {
                    name     = "tangent@" + _mesh.name,
                    offset   = offsetTangent,
                    count    = _mesh.vertexCount,
                    compType = ComponentType.FLOAT32,
                    attrType = AttrType.VEC4,
                    min      = new object[4] {
                        minTangent.x, minTangent.y, minTangent.z, minTangent.w
                    },
                    max = new object[4] {
                        maxTangent.x, maxTangent.y, maxTangent.z, maxTangent.w
                    },
                };

                vbView.accessors.Add(acc);
            }

            if (colors.Length > 0)
            {
                AccessorInfo acc = new AccessorInfo
                {
                    name     = "color@" + _mesh.name,
                    offset   = offsetColor,
                    count    = _mesh.vertexCount,
                    compType = ComponentType.FLOAT32,
                    attrType = AttrType.VEC4,
                    // TODO: min, max
                };

                vbView.accessors.Add(acc);
            }

            if (uv.Length > 0)
            {
                AccessorInfo acc = new AccessorInfo
                {
                    name     = "uv0@" + _mesh.name,
                    offset   = offsetUV,
                    count    = _mesh.vertexCount,
                    compType = ComponentType.FLOAT32,
                    attrType = AttrType.VEC2,
                    // TODO: min, max
                };

                vbView.accessors.Add(acc);
            }

            if (uv2.Length > 0)
            {
                AccessorInfo acc = new AccessorInfo
                {
                    name     = "uv1@" + _mesh.name,
                    offset   = offsetUV2,
                    count    = _mesh.vertexCount,
                    compType = ComponentType.FLOAT32,
                    attrType = AttrType.VEC2,
                    // TODO: min, max
                };

                vbView.accessors.Add(acc);
            }

            if (uv3.Length > 0)
            {
                AccessorInfo acc = new AccessorInfo
                {
                    name     = "uv2@" + _mesh.name,
                    offset   = offsetUV3,
                    count    = _mesh.vertexCount,
                    compType = ComponentType.FLOAT32,
                    attrType = AttrType.VEC2,
                    // TODO: min, max
                };

                vbView.accessors.Add(acc);
            }

            if (uv4.Length > 0)
            {
                AccessorInfo acc = new AccessorInfo
                {
                    name     = "uv3@" + _mesh.name,
                    offset   = offsetUV4,
                    count    = _mesh.vertexCount,
                    compType = ComponentType.FLOAT32,
                    attrType = AttrType.VEC2,
                    // TODO: min, max
                };

                vbView.accessors.Add(acc);
            }

            if (boneWeights.Length > 0)
            {
                AccessorInfo acc = new AccessorInfo
                {
                    name     = "joints@" + _mesh.name,
                    offset   = offsetJoint,
                    count    = _mesh.vertexCount,
                    compType = ComponentType.UINT16,
                    attrType = AttrType.VEC4,
                    // TODO: min, max
                };

                vbView.accessors.Add(acc);

                acc = new AccessorInfo
                {
                    name     = "weights@" + _mesh.name,
                    offset   = offsetWeight,
                    count    = _mesh.vertexCount,
                    compType = ComponentType.FLOAT32,
                    attrType = AttrType.VEC4,
                    // TODO: min, max
                };

                vbView.accessors.Add(acc);
            }

            //
            bufferViews.Add(vbView);
            offsetBuffer += Utils.Align(vbView.length, 4);

            // ibView
            for (int i = 0; i < indexDataList.Count; ++i)
            {
                byte[] indexData = indexDataList[i];

                BufferViewInfo ibView = new BufferViewInfo
                {
                    name      = "ib" + i + "@" + _mesh.name,
                    offset    = offsetBuffer,
                    length    = indexData.Length,
                    type      = BufferType.INDEX,
                    accessors = new List <AccessorInfo>(),
                };

                AccessorInfo acc = new AccessorInfo
                {
                    name     = "indices" + i + "@" + _mesh.name,
                    offset   = 0,
                    count    = indexData.Length / 2,
                    compType = ComponentType.UINT16,
                    attrType = AttrType.SCALAR,
                };

                ibView.accessors.Add(acc);

                bufferViews.Add(ibView);
                offsetBuffer += Utils.Align(ibView.length, 4);
            }

            // bpView
            if (bindposesData.Length > 0)
            {
                BufferViewInfo bpView = new BufferViewInfo
                {
                    name      = "bp@" + _mesh.name,
                    offset    = offsetBuffer,
                    length    = bindposesData.Length,
                    type      = BufferType.NONE,
                    accessors = new List <AccessorInfo>(),
                };

                AccessorInfo acc = new AccessorInfo
                {
                    name     = "bindposes@" + _mesh.name,
                    offset   = 0,
                    count    = bindposesData.Length / (4 * 16),
                    compType = ComponentType.FLOAT32,
                    attrType = AttrType.MAT4,
                };

                bpView.accessors.Add(acc);

                bufferViews.Add(bpView);
                offsetBuffer += Utils.Align(bpView.length, 4);
            }

            // data
            byte[] data   = new byte[offsetBuffer];
            int    offset = 0;

            System.Buffer.BlockCopy(_bufInfo.data, 0, data, offset, _bufInfo.data.Length);
            offset += _bufInfo.data.Length;

            System.Buffer.BlockCopy(vertexData, 0, data, offset, vertexData.Length);
            offset += Utils.Align(vertexData.Length, 4);

            for (int i = 0; i < indexDataList.Count; ++i)
            {
                System.Buffer.BlockCopy(indexDataList[i], 0, data, offset, indexDataList[i].Length);
                offset += Utils.Align(indexDataList[i].Length, 4);
            }

            System.Buffer.BlockCopy(bindposesData, 0, data, offset, bindposesData.Length);
            offset += Utils.Align(bindposesData.Length, 4);

            //
            _bufInfo.data = data;
            _bufInfo.bufferViews.AddRange(bufferViews);
        }
Exemple #3
0
        Dictionary <string, JSON_Asset> saveAssets(
            string dest,
            List <Object> prefabs,
            List <Object> modelPrefabs,
            List <Mesh> meshes,
            List <Texture> textures,
            List <Texture> spriteTextures,
            List <Material> materials,
            List <Font> fonts
            )
        {
            Dictionary <string, JSON_Asset> assetsJson = new Dictionary <string, JSON_Asset>();

            // DELME {
            // // save meshes
            // var destMeshes = Path.Combine(dest, "meshes");
            // foreach (Mesh mesh in meshes) {
            //   string id = Utils.AssetID(mesh);
            //   GLTF gltf = new GLTF();
            //   gltf.asset = new GLTF_Asset
            //   {
            //     version = "1.0.0",
            //     generator = "u3d-exporter"
            //   };
            //   BufferInfo bufInfo = new BufferInfo
            //   {
            //     id = id,
            //     name = mesh.name
            //   };

            //   DumpMesh(mesh, gltf, bufInfo, 0);
            //   DumpBuffer(bufInfo, gltf);

            //   Save(
            //     destMeshes,
            //     id,
            //     gltf,
            //     new List<BufferInfo> { bufInfo }
            //   );

            //   // add asset to table
            //   assetsJson.Add(id, new JSON_Asset {
            //     type = "mesh",
            //     urls = new Dictionary<string, string> {
            //       { "gltf", "meshes/" + id + ".gltf" },
            //       { "bin", "meshes/" + id + ".bin" }
            //     }
            //   });
            // }
            // } DELME

            // ========================================
            // save animations
            // ========================================

            var destAnims = Path.Combine(dest, "anims");

            foreach (GameObject prefab in prefabs)
            {
                // skip ModelPrefab
                if (PrefabUtility.GetPrefabType(prefab) == PrefabType.ModelPrefab)
                {
                    Debug.LogWarning("Can not export model prefab " + prefab.name + " in the scene");
                    continue;
                }

                // skip non-animation prefab
                bool isAnimPrefab = Utils.IsAnimPrefab(prefab);
                if (isAnimPrefab == false)
                {
                    continue;
                }

                // get animations
                GameObject           prefabInst = PrefabUtility.InstantiatePrefab(prefab) as GameObject;
                List <AnimationClip> clips      = Utils.GetAnimationClips(prefabInst);

                // get joints
                List <GameObject> joints = new List <GameObject>();
                Utils.RecurseNode(prefabInst, _go => {
                    // this is not a joint
                    if (_go.GetComponent <SkinnedMeshRenderer>() != null)
                    {
                        return(false);
                    }

                    joints.Add(_go);
                    return(true);
                });

                // dump animation clips
                if (clips != null)
                {
                    // process AnimationClip(s)
                    foreach (AnimationClip clip in clips)
                    {
                        string id   = Utils.AssetID(clip);
                        GLTF   gltf = new GLTF();
                        gltf.asset = new GLTF_Asset {
                            version   = "1.0.0",
                            generator = "u3d-exporter"
                        };
                        BufferInfo bufInfo = new BufferInfo {
                            id   = id,
                            name = prefab.name
                        };

                        AnimData animData = DumpAnimData(prefabInst, clip);
                        DumpBufferInfoFromAnimData(animData, bufInfo);

                        GLTF_AnimationEx gltfAnim = DumpGltfAnimationEx(animData, joints, 0);
                        gltf.animations.Add(gltfAnim);

                        DumpBuffer(bufInfo, gltf);

                        Save(
                            destAnims,
                            id + ".anim",
                            gltf,
                            new List <BufferInfo> {
                            bufInfo
                        }
                            );

                        // add asset to table
                        try {
                            if (!assetsJson.ContainsKey(id))
                            {
                                assetsJson.Add(id, new JSON_Asset {
                                    type = "animation",
                                    urls = new Dictionary <string, string> {
                                        { "anim", "anims/" + id + ".anim" },
                                        { "bin", "anims/" + id + ".bin" }
                                    }
                                });
                            }
                        } catch (System.SystemException e) {
                            Debug.LogError("Failed to add " + id + " to assets: " + e);
                        }
                    }
                }

                Object.DestroyImmediate(prefabInst);
            }

            // ========================================
            // save prefabs
            // ========================================

            var destMeshes  = Path.Combine(dest, "meshes");
            var destPrefabs = Path.Combine(dest, "prefabs");

            // create dest directory
            if (!Directory.Exists(destMeshes))
            {
                Directory.CreateDirectory(destMeshes);
            }
            if (!Directory.Exists(destPrefabs))
            {
                Directory.CreateDirectory(destPrefabs);
            }

            foreach (GameObject prefab in prefabs)
            {
                string id = Utils.AssetID(prefab);

                // save prefabs
                if (PrefabUtility.GetPrefabType(prefab) == PrefabType.ModelPrefab)
                {
                    Debug.LogWarning("Can not export model prefab " + prefab.name + " in the scene");
                    continue;
                }
                var    prefabJson = DumpPrefab(prefab);
                string path;
                string json = JsonConvert.SerializeObject(prefabJson, Formatting.Indented);

                path = Path.Combine(destPrefabs, id + ".json");
                StreamWriter writer = new StreamWriter(path);
                writer.Write(json);
                writer.Close();

                // Debug.Log(Path.GetFileName(path) + " saved.");

                // add asset to table
                if (!assetsJson.ContainsKey(id))
                {
                    assetsJson.Add(id, new JSON_Asset {
                        type = "prefab",
                        urls = new Dictionary <string, string> {
                            { "json", "prefabs/" + id + ".json" },
                        }
                    });
                }
            }

            // save model prefab (as gltf)
            foreach (GameObject modelPrefab in modelPrefabs)
            {
                string id = Utils.AssetID(modelPrefab);
                // save model prefabs
                GLTF gltf = new GLTF();
                gltf.asset = new GLTF_Asset {
                    version   = "1.0.0",
                    generator = "u3d-exporter"
                };
                BufferInfo bufInfo = new BufferInfo {
                    id   = id,
                    name = modelPrefab.name
                };

                bool isAnimPrefab = Utils.IsAnimPrefab(modelPrefab);
                if (isAnimPrefab)
                {
                    DumpSkinningModel(modelPrefab, gltf, bufInfo);
                    DumpBuffer(bufInfo, gltf);
                }
                else
                {
                    DumpModel(modelPrefab, gltf, bufInfo);
                    DumpBuffer(bufInfo, gltf);
                }

                Save(
                    destMeshes,
                    id + ".gltf",
                    gltf,
                    new List <BufferInfo> {
                    bufInfo
                }
                    );

                // add asset to table
                if (!assetsJson.ContainsKey(id))
                {
                    assetsJson.Add(id, new JSON_Asset {
                        type = "gltf",
                        urls = new Dictionary <string, string> {
                            { "gltf", "meshes/" + id + ".gltf" },
                            { "bin", "meshes/" + id + ".bin" }
                        }
                    });
                }
            }

            // save meshes (as gltf)
            foreach (Mesh mesh in meshes)
            {
                string id = Utils.AssetID(mesh);
                // save model prefabs
                GLTF gltf = new GLTF();
                gltf.asset = new GLTF_Asset {
                    version   = "1.0.0",
                    generator = "u3d-exporter"
                };
                BufferInfo bufInfo = new BufferInfo {
                    id   = id,
                    name = mesh.name
                };

                DumpMesh(mesh, gltf, bufInfo, 0);
                DumpBuffer(bufInfo, gltf);

                Save(
                    destMeshes,
                    id + ".mesh",
                    gltf,
                    new List <BufferInfo> {
                    bufInfo
                }
                    );

                // add asset to table
                if (!assetsJson.ContainsKey(id))
                {
                    assetsJson.Add(id, new JSON_Asset {
                        type = "mesh",
                        urls = new Dictionary <string, string> {
                            { "mesh", "meshes/" + id + ".mesh" },
                            { "bin", "meshes/" + id + ".bin" }
                        }
                    });
                }
            }

            // ========================================
            // save textures
            // ========================================

            var destTextures = Path.Combine(dest, "textures");

            // create dest directory
            if (!Directory.Exists(destTextures))
            {
                Directory.CreateDirectory(destTextures);
            }
            foreach (Texture tex in textures)
            {
                var    textureJson = DumpTexture(tex);
                string path;
                string json = JsonConvert.SerializeObject(textureJson, Formatting.Indented);
                string id   = Utils.AssetID(tex);

                // json
                path = Path.Combine(destTextures, id + ".json");
                StreamWriter writer = new StreamWriter(path);
                writer.Write(json);
                writer.Close();

                // image
                string assetPath = AssetDatabase.GetAssetPath(tex);
                path = Path.Combine(destTextures, id + Utils.AssetExt(tex));
                File.Copy(assetPath, path, true);

                // Debug.Log(Path.GetFileName(path) + " saved.");

                // add asset to table
                if (!assetsJson.ContainsKey(id))
                {
                    assetsJson.Add(id, new JSON_Asset {
                        type = "texture",
                        urls = new Dictionary <string, string> {
                            { "json", "textures/" + id + ".json" },
                            { "image", "textures/" + id + Utils.AssetExt(tex) },
                        }
                    });
                }
            }

            // ========================================
            // save sprite textures
            // ========================================

            var destSprites = Path.Combine(dest, "sprites");

            // create dest directory
            if (!Directory.Exists(destSprites))
            {
                Directory.CreateDirectory(destSprites);
            }
            foreach (Texture spriteTex in spriteTextures)
            {
                var    spriteTextureJson = DumpSpriteTexture(spriteTex);
                string path;
                string json = JsonConvert.SerializeObject(spriteTextureJson, Formatting.Indented);
                string id   = Utils.AssetID(spriteTex);

                // json
                path = Path.Combine(destSprites, id + ".json");
                StreamWriter writer = new StreamWriter(path);
                writer.Write(json);
                writer.Close();

                // image
                string assetPath = AssetDatabase.GetAssetPath(spriteTex);
                path = Path.Combine(destSprites, id + Utils.AssetExt(spriteTex));
                File.Copy(assetPath, path);

                // add asset to table
                if (!assetsJson.ContainsKey(id))
                {
                    assetsJson.Add(id, new JSON_Asset {
                        type = "texture",
                        urls = new Dictionary <string, string> {
                            { "json", "sprites/" + id + ".json" },
                            { "image", "sprites/" + id + Utils.AssetExt(spriteTex) },
                        }
                    });
                }
            }

            // ========================================
            // save fonts
            // ========================================

            var destFonts = Path.Combine(dest, "fonts");

            if (!Directory.Exists(destFonts))
            {
                Directory.CreateDirectory(destFonts);
            }

            foreach (Font font in fonts)
            {
                if (font.dynamic)
                {
                    if (font.fontNames.Length > 1) // system font
                    // do nothing
                    {
                    }
                    else // opentype font
                    {
                        JSON_OpenTypeFont fontJson = DumpOpenTypeFont(font);

                        // save font json
                        string path;
                        string json = JsonConvert.SerializeObject(fontJson, Formatting.Indented);
                        string id   = Utils.AssetID(font);

                        path = Path.Combine(destFonts, id + ".json");
                        StreamWriter writer = new StreamWriter(path);
                        writer.Write(json);
                        writer.Close();

                        // save font file (ttf)
                        Texture tex       = font.material.mainTexture;
                        string  assetPath = AssetDatabase.GetAssetPath(font);
                        path = Path.Combine(destFonts, id + Utils.AssetExt(font));
                        File.Copy(assetPath, path, true);

                        if (!assetsJson.ContainsKey(id))
                        {
                            assetsJson.Add(id, new JSON_Asset {
                                type = "otfont",
                                urls = new Dictionary <string, string> {
                                    { "json", "fonts/" + id + ".json" },
                                    { "bin", "fonts/" + id + Utils.AssetExt(font) },
                                }
                            });
                        }
                    }
                }
                else // bitmapFont
                {
                    JSON_BitmapFont fontJson = DumpBitmapFont(font);

                    string path;
                    string json = JsonConvert.SerializeObject(fontJson, Formatting.Indented);
                    string id   = Utils.AssetID(font);

                    path = Path.Combine(destFonts, id + ".json");
                    StreamWriter writer = new StreamWriter(path);
                    writer.Write(json);
                    writer.Close();

                    if (!assetsJson.ContainsKey(id))
                    {
                        assetsJson.Add(id, new JSON_Asset {
                            type = "bmfont",
                            urls = new Dictionary <string, string> {
                                { "json", "fonts/" + id + ".json" },
                            }
                        });
                    }
                }
            }

            // ========================================
            // save materials
            // ========================================

            var destMaterials = Path.Combine(dest, "materials");

            // create dest directory
            if (!Directory.Exists(destMaterials))
            {
                Directory.CreateDirectory(destMaterials);
            }
            foreach (Material mat in materials)
            {
                var materialJson = DumpMaterial(mat);
                if (materialJson == null)
                {
                    continue;
                }

                string path;
                string json = JsonConvert.SerializeObject(materialJson, Formatting.Indented);
                string id   = Utils.AssetID(mat);

                // json
                path = Path.Combine(destMaterials, id + ".json");
                StreamWriter writer = new StreamWriter(path);
                writer.Write(json);
                writer.Close();

                // Debug.Log(Path.GetFileName(path) + " saved.");

                // add asset to table
                if (!assetsJson.ContainsKey(id))
                {
                    assetsJson.Add(id, new JSON_Asset {
                        type = "material",
                        urls = new Dictionary <string, string> {
                            { "json", "materials/" + id + ".json" },
                        }
                    });
                }
            }

            // ========================================
            // save assets
            // ========================================

            {
                string path = Path.Combine(dest, "assets.json");
                string json = JsonConvert.SerializeObject(assetsJson, Formatting.Indented);

                StreamWriter writer = new StreamWriter(path);
                writer.Write(json);
                writer.Close();
            }

            return(assetsJson);
        }
        // -----------------------------------------
        // DumpBufferInfoFromAnimData
        // -----------------------------------------

        void DumpBufferInfoFromAnimData(AnimData _animData, BufferInfo _bufInfo)
        {
            List <AccessorInfo> accessors = new List <AccessorInfo>();

            // calculate total length of animation-data
            int          length = 0;
            AccessorInfo acc;

            // time0
            acc = new AccessorInfo
            {
                name     = "time0@" + _animData.name,
                offset   = length,
                count    = 1,
                compType = ComponentType.FLOAT32,
                attrType = AttrType.SCALAR
            };

            accessors.Add(acc);
            length += 4;

            // times
            acc = new AccessorInfo
            {
                name     = "times@" + _animData.name,
                offset   = length,
                count    = _animData.times.Count,
                compType = ComponentType.FLOAT32,
                attrType = AttrType.SCALAR
            };

            accessors.Add(acc);
            length += _animData.times.Count * 4;

            // frames
            foreach (var entry in _animData.nameToFrames)
            {
                NodeFrames frames = entry.Value;

                if (frames.tlist.Count > 0)
                {
                    acc = new AccessorInfo
                    {
                        name     = frames.node.name + "_T@" + _animData.name,
                        offset   = length,
                        count    = frames.tlist.Count,
                        compType = ComponentType.FLOAT32,
                        attrType = AttrType.VEC3
                    };

                    accessors.Add(acc);
                    length += frames.tlist.Count * 12;
                }

                if (frames.slist.Count > 0)
                {
                    acc = new AccessorInfo
                    {
                        name     = frames.node.name + "_S@" + _animData.name,
                        offset   = length,
                        count    = frames.slist.Count,
                        compType = ComponentType.FLOAT32,
                        attrType = AttrType.VEC3
                    };

                    accessors.Add(acc);
                    length += frames.slist.Count * 12;
                }

                if (frames.rlist.Count > 0)
                {
                    acc = new AccessorInfo
                    {
                        name     = frames.node.name + "_R@" + _animData.name,
                        offset   = length,
                        count    = frames.rlist.Count,
                        compType = ComponentType.FLOAT32,
                        attrType = AttrType.VEC4
                    };

                    accessors.Add(acc);
                    length += frames.rlist.Count * 16;
                }
            }

            // write data
            byte[] clipData;
            using (MemoryStream stream = new MemoryStream(length)) {
                using (BinaryWriter writer = new BinaryWriter(stream)) {
                    // time0
                    writer.Write(0.0f);

                    // times
                    for (int i = 0; i < _animData.times.Count; ++i)
                    {
                        writer.Write(_animData.times[i]);
                    }

                    foreach (var entry in _animData.nameToFrames)
                    {
                        NodeFrames frames = entry.Value;

                        if (frames.tlist.Count > 0)
                        {
                            for (int i = 0; i < frames.tlist.Count; ++i)
                            {
                                // NOTE: convert LH to RH
                                writer.Write(frames.tlist[i].x);
                                writer.Write(frames.tlist[i].y);
                                writer.Write(-frames.tlist[i].z);
                            }
                        }

                        if (frames.slist.Count > 0)
                        {
                            for (int i = 0; i < frames.slist.Count; ++i)
                            {
                                writer.Write(frames.slist[i].x);
                                writer.Write(frames.slist[i].y);
                                writer.Write(frames.slist[i].z);
                            }
                        }

                        if (frames.rlist.Count > 0)
                        {
                            for (int i = 0; i < frames.rlist.Count; ++i)
                            {
                                // NOTE: convert LH to RH
                                writer.Write(-frames.rlist[i].x);
                                writer.Write(-frames.rlist[i].y);
                                writer.Write(frames.rlist[i].z);
                                writer.Write(frames.rlist[i].w);
                            }
                        }
                    }
                }
                clipData = stream.ToArray();
            }

            // buffer view
            BufferViewInfo bufView = new BufferViewInfo
            {
                name      = _animData.name,
                offset    = _bufInfo.data.Length,
                length    = clipData.Length,
                type      = BufferType.NONE,
                accessors = accessors
            };

            //
            byte[] data   = new byte[_bufInfo.data.Length + clipData.Length];
            int    offset = 0;

            System.Buffer.BlockCopy(_bufInfo.data, 0, data, offset, _bufInfo.data.Length);
            offset += _bufInfo.data.Length;

            System.Buffer.BlockCopy(clipData, 0, data, offset, clipData.Length);
            offset += clipData.Length;

            //
            _bufInfo.data = data;
            _bufInfo.bufferViews.Add(bufView);
        }
Exemple #5
0
        // -----------------------------------------
        // DumpSkinningModel
        // -----------------------------------------

        void DumpSkinningModel(GameObject _prefab, GLTF _gltf, BufferInfo _bufInfo)
        {
            // get joints
            List <GameObject> joints = new List <GameObject>();

            Utils.RecurseNode(_prefab, _go => {
                // this is not a joint
                if (_go.GetComponent <SkinnedMeshRenderer>() != null)
                {
                    return(false);
                }

                joints.Add(_go);
                return(true);
            });

            // get nodes
            List <GameObject> nodes = new List <GameObject>();

            Utils.RecurseNode(_prefab, _go => {
                // this is a joint, skip it.
                if (_go.GetComponents <Component>().Length == 1)
                {
                    return(false);
                }

                nodes.Add(_go);
                return(true);
            });

            // get skins & meshes
            List <Mesh> meshes = new List <Mesh>();
            List <SkinnedMeshRenderer> smrList = new List <SkinnedMeshRenderer>();

            Utils.RecurseNode(_prefab, _go => {
                SkinnedMeshRenderer smr = _go.GetComponent <SkinnedMeshRenderer>();
                if (smr != null)
                {
                    meshes.Add(smr.sharedMesh);
                    smrList.Add(smr);
                }

                return(true);
            });

            // dump nodes
            foreach (GameObject go in nodes)
            {
                GLTF_Node gltfNode = DumpGltfNode(go, nodes);

                SkinnedMeshRenderer smr = go.GetComponent <SkinnedMeshRenderer>();
                if (smr != null)
                {
                    gltfNode.mesh = meshes.IndexOf(smr.sharedMesh);
                    gltfNode.skin = smrList.IndexOf(smr);
                }

                _gltf.nodes.Add(gltfNode);
            }

            // dump joints
            foreach (GameObject go in joints)
            {
                GLTF_Node gltfNode = DumpGltfNode(go, joints);
                _gltf.joints.Add(gltfNode);
            }

            // dump meshes & skin
            int accOffset = 0;

            foreach (SkinnedMeshRenderer smr in smrList)
            {
                // dump mesh
                accOffset = _bufInfo.GetAccessorCount();
                DumpMesh(smr.sharedMesh, _gltf, _bufInfo, accOffset);

                // dump skin
                int        accBindposesIdx = _bufInfo.GetAccessorCount() - 1;
                GameObject rootBone        = Utils.GetRootBone(smr, _prefab).gameObject;

                GLTF_Skin gltfSkin = DumpGtlfSkin(smr, joints, rootBone, accBindposesIdx);
                if (gltfSkin != null)
                {
                    _gltf.skins.Add(gltfSkin);
                }
            }
        }