Beispiel #1
0
        protected virtual IEnumerator LoadImage(string rootPath, GLTF.Schema.Image image, int imageID)
        {
            if (_assetCache.ImageCache[imageID] == null)
            {
                Texture2D texture = null;
                if (image.Uri != null)
                {
                    var uri = image.Uri;

                    Regex regex = new Regex(Base64StringInitializer);
                    Match match = regex.Match(uri);
                    if (match.Success)
                    {
                        var base64Data  = uri.Substring(match.Length);
                        var textureData = Convert.FromBase64String(base64Data);
                        texture = new Texture2D(0, 0);
                        texture.LoadImage(textureData);
                    }
                    else if (_loadType == LoadType.Uri)
                    {
                        var www = UnityWebRequest.Get(Path.Combine(rootPath, uri));
                        www.downloadHandler = new DownloadHandlerTexture();

                        yield return(www.Send());

                        // HACK to enable mipmaps :(
                        var tempTexture = DownloadHandlerTexture.GetContent(www);
                        if (tempTexture != null)
                        {
                            texture = new Texture2D(tempTexture.width, tempTexture.height, tempTexture.format, true);
                            texture.SetPixels(tempTexture.GetPixels());
                            texture.Apply(true);
                        }
                        else
                        {
                            Debug.LogFormat("{0} {1}", www.responseCode, www.url);
                            texture = new Texture2D(16, 16);
                        }
                    }
                    else if (_loadType == LoadType.Stream)
                    {
                        var    pathToLoad = Path.Combine(rootPath, uri);
                        var    file       = File.OpenRead(pathToLoad);
                        byte[] bufferData = new byte[file.Length];
                        file.Read(bufferData, 0, (int)file.Length);
#if !WINDOWS_UWP
                        file.Close();
#else
                        file.Dispose();
#endif
                        texture = new Texture2D(0, 0);
                        texture.LoadImage(bufferData);
                    }
                }
                else
                {
                    texture = new Texture2D(0, 0);
                    var bufferView = image.BufferView.Value;
                    var buffer     = bufferView.Buffer.Value;
                    var data       = new byte[bufferView.ByteLength];

                    var bufferContents = _assetCache.BufferCache[bufferView.Buffer.Id];
                    System.Buffer.BlockCopy(bufferContents, bufferView.ByteOffset, data, 0, data.Length);
                    texture.LoadImage(data);
                }

                _assetCache.ImageCache[imageID] = texture;
            }
        }
Beispiel #2
0
        /// <summary>
        /// Creates a scene based off loaded JSON. Includes loading in binary and image data to construct the meshes required.
        /// </summary>
        /// <param name="sceneIndex">The index of scene in gltf file to load</param>
        /// <param name="isMultithreaded">Whether to use a thread to do loading</param>
        /// <returns></returns>
        protected IEnumerator ImportScene(int sceneIndex = -1, bool isMultithreaded = false)
        {
            GLTF.Schema.Scene scene;
            if (sceneIndex >= 0 && sceneIndex < _root.Scenes.Count)
            {
                scene = _root.Scenes[sceneIndex];
            }
            else
            {
                scene = _root.GetDefaultScene();
            }

            if (scene == null)
            {
                throw new Exception("No default scene in gltf file.");
            }

            _assetCache = new AssetCache(
                _root.Images != null ? _root.Images.Count : 0,
                _root.Textures != null ? _root.Textures.Count : 0,
                _root.Materials != null ? _root.Materials.Count : 0,
                _root.Buffers != null ? _root.Buffers.Count : 0,
                _root.Meshes != null ? _root.Meshes.Count : 0
                );

            if (_lastLoadedScene == null)
            {
                if (_root.Buffers != null)
                {
                    // todo add fuzzing to verify that buffers are before uri
                    for (int i = 0; i < _root.Buffers.Count; ++i)
                    {
                        GLTF.Schema.Buffer buffer = _root.Buffers[i];
                        if (buffer.Uri != null)
                        {
                            yield return(LoadBuffer(_gltfDirectoryPath, buffer, i));
                        }
                        else                         //null buffer uri indicates GLB buffer loading
                        {
                            byte[] glbBuffer;
                            GLTFParser.ExtractBinaryChunk(_gltfData, i, out glbBuffer);
                            _assetCache.BufferCache[i] = glbBuffer;
                        }
                    }
                }

                if (_root.Images != null)
                {
                    for (int i = 0; i < _root.Images.Count; ++i)
                    {
                        GLTF.Schema.Image image = _root.Images[i];
                        yield return(LoadImage(_gltfDirectoryPath, image, i));
                    }
                }
#if !WINDOWS_UWP
                // generate these in advance instead of as-needed
                if (isMultithreaded)
                {
                    yield return(_asyncAction.RunOnWorkerThread(() => BuildAttributesForMeshes()));
                }
#endif
            }

            var sceneObj = CreateScene(scene);

            if (_sceneParent != null)
            {
                sceneObj.transform.SetParent(_sceneParent, false);
            }

            // Experiment with fitting the scene into a prescribed size by accumulating
            // all of the scenes nodes bounding boxes and then scaling the root node
            // (I think this would be better as a mode to scale vertices but not for now..)
            var allRenderersInScene = sceneObj.GetComponentsInChildren <Renderer>(false);

            Bounds?box = null;

            foreach (var renderer in allRenderersInScene)
            {
                //CreateBox(sceneObj.transform, renderer.bounds);

                if (!box.HasValue)
                {
                    box = new Bounds(renderer.bounds.center, renderer.bounds.size);
                }
                else
                {
                    var val = box.Value;
                    val.Encapsulate(renderer.bounds);
                    box = val;
                }
            }

            //CreateBox(sceneObj.transform, box);

            // Now, for each individual mesh we can move the pivot to the bottom/centre
            // w.r.t the vertices. This way we can easily place models on a flat surface
            var allMeshesInScene = sceneObj.GetComponentsInChildren <MeshFilter>(false);
            foreach (var renderer in allMeshesInScene)
            {
                var bbox = renderer.mesh.bounds;

                // Calculate the distances we need to shift all of the vertices in
                // each direction to get them centred in x and z and have them sitting
                // at zero in the y-axis
                float adjustY = bbox.center.y;
                float adjustx = bbox.center.x;
                float adjustZ = bbox.center.z;

                //var verts = renderer.mesh.vertices;
                //for (int i = 0; i < verts.Length; i++)
                //{
                //    verts[i].x = verts[i].x - adjustx;
                //    verts[i].y = verts[i].y - adjustY;
                //    verts[i].z = verts[i].z - adjustZ;
                //}

                //renderer.mesh.vertices = verts;
            }


            Vector3 targetSize      = Vector3.one / 4.0f;
            Vector3 sceneBoundsSize = box.Value.max - box.Value.min;

            float ratioX = targetSize.x / sceneBoundsSize.x;
            float ratioY = targetSize.y / sceneBoundsSize.y;
            float ratioZ = targetSize.z / sceneBoundsSize.z;

            float biggest = Math.Min(ratioZ, Math.Min(ratioX, ratioY));

            //sceneObj.transform.localScale = sceneObj.transform.localScale *
            //    (componentMax(targetSize) / componentMax(sceneBoundsSize));

            //float f = componentMax(div(targetSize, sceneBoundsSize));

            sceneObj.transform.localScale = sceneObj.transform.localScale * biggest;

            _lastLoadedScene = sceneObj;
        }