/**
         * Downloads a file to a local path, then loads the file
         */
        private IEnumerator DownloadFile(ModelDataTemplate.ModelImportData modelData, Text progressDisplay, int index, string localPathAndFilename, System.Action <ModelFile> callback = null)
        {
            UnityWebRequest fileDownloader = UnityWebRequest.Get(modelData.url);

            //get size of model first to allocate what is needed
            long modelSize = 0;

            yield return(StartCoroutine(GetFileSize(modelData.url, (size) =>
            {
                modelSize = size;
            })
                                        ));

            //set our model download settings
            fileDownloader.method = UnityWebRequest.kHttpVerbGET;
            using (var dh = new DownloadHandlerFile(localPathAndFilename))
            {
                dh.removeFileOnAbort           = true;
                fileDownloader.downloadHandler = dh;
                fileDownloader.SendWebRequest();

                while (!fileDownloader.isDone)
                {
                    string stats = WebGLMemoryStats.GetMoreStats("Downloading");
                    progressDisplay.text = $"Downloading {modelData.name}: {fileDownloader.downloadProgress.ToString("P")}\n{stats}";

                    yield return(null);
                }
            }

            System.GC.Collect();

            //Debug.Log($"Successfully downloaded model {modelData.name}, size {fileDownloader.downloadedBytes} bytes.");

            if (fileDownloader.result == UnityWebRequest.Result.ConnectionError || fileDownloader.result == UnityWebRequest.Result.ProtocolError)
            {
                Debug.LogError(fileDownloader.error);
            }

            //Debug.Log($"Successfully downloaded asset {assetData.name}, size {fileDownloader.downloadedBytes} bytes.");

            ulong downloadedSize = fileDownloader.downloadedBytes;

            fileDownloader = null;

            callback(new ModelFile(localPathAndFilename, modelData.name, downloadedSize));
        }
        public IEnumerator TryLoadLocalFile(string localPathAndFileName, string name, ulong downloadedSize, Text progressDisplay, System.Action <GameObject> callback)
        {
            progressDisplay.text = $"{name}: Measuring file size";

            WebGLMemoryStats.LogMoreStats($"--- TryLoadLocalFile {name} ---");

            bool canAnalyze = WebGLMemoryStats.HasEnoughMemoryToLoadBytes((long)downloadedSize);

            Debug.Log($"File size: {WebGLMemoryStats.ToRoundedMB(downloadedSize, 2)}MB.");

            if (!canAnalyze)
            {
                Debug.Log($"{name} too large to analyze. Loading error model instead.");
                callback(CreateFailureObject("Model too large to analyze."));
                yield break;
            }

            progressDisplay.text = $"{name}: Estimating memory requirements";

            GLBMemoryMeasurer.SetModel(localPathAndFileName);

            uint memorySize = GLBMemoryMeasurer.EstimateSize();

            Debug.Log($"Est. memory size: {WebGLMemoryStats.ToRoundedMB(memorySize, 2)}MB.");

            bool canInstantiate = WebGLMemoryStats.HasEnoughMemoryToLoadBytes((long)memorySize);

            if (!canInstantiate)
            {
                //TODO(Brandon):
                // delete local file? to free it from memory? or let OS GC do that?
                // download placeholder / error file then call callback on it
                // OR call callback with a placeholder error file
                // create a button that lets you TRY to reload it?
                Debug.Log($"{name} too large to instantiate. Loading error model instead.");
                callback(CreateFailureObject("Model too large to instantiate."));
                yield break;
            }

            progressDisplay.text = $"{name}: Instantiating";

            LoadLocalFile(localPathAndFileName, callback);
        }
예제 #3
0
        public static uint EstimateSize()
        {
            uint totalSize = 0;

            uint totalTriangles = 0;
            uint totalVertices  = 0;

            //WebGLMemoryStats.LogMoreStats("GLBMemoryMeasurer.EstimateSize Meshes BEFORE");
            for (int i = 0; i < _primitives.Count; i += 1)
            {
                uint size = MeshMemoryMeasurer.EstimateSize(_primitives[i].triangles, _primitives[i].vertices);

                totalSize += size;

                totalTriangles += _primitives[i].triangles;
                totalVertices  += _primitives[i].vertices;
            }
            //WebGLMemoryStats.LogMoreStats("GLBMemoryMeasurer.EstimateSize Meshes AFTER");

            Debug.Log($"Estimated size (meshes): {WebGLMemoryStats.ToRoundedMB(totalSize, 2)} MB.                  ({totalVertices} vertices, {totalTriangles} triangles)");

            for (int i = 0; i < _textures.Count; i += 1)
            {
                //WebGLMemoryStats.LogMoreStats("GLBMemoryMeasurer.EstimateSize Textures BEFORE");

                uint size = TextureMemoryMeasurer.EstimateSize(_textures[i].width, _textures[i].height, _textures[i].bitDepth, _textures[i].samples, _textures[i].isMipMapOn);

                //WebGLMemoryStats.LogMoreStats("GLBMemoryMeasurer.EstimateSize Textures AFTER");

                totalSize += size;

                Debug.Log($"Estimated texture #{i} size: {WebGLMemoryStats.ToRoundedMB(size, 2)} MB.                  {_textures[i].width}x{_textures[i].height} / {_textures[i].bitDepth}-bit depth / {_textures[i].samples} samples / mipmap = {_textures[i].isMipMapOn}.");
            }

            //Debug.Log($"Estimated size (total): {WebGLMemoryStats.ToRoundedMB(totalSize, 2)} MB.");

            return(totalSize);
        }