public Unity3DTile(Unity3DTileset tileset, string basePath, Schema.Tile tile, Unity3DTile parent) { this.hashCode = (int)UnityEngine.Random.Range(0, int.MaxValue); this.Tileset = tileset; this.tile = tile; this.FrameState = new TileFrameState(); if (tile.Content != null) { this.Id = Path.GetFileNameWithoutExtension(tile.Content.GetUri()); } if (parent != null) { parent.Children.Add(this); this.Depth = parent.Depth + 1; } // TODO: Consider using a double percision Matrix library for doing 3d tiles root transform calculations // Set the local transform for this tile, default to identity matrix this.transform = this.tile.UnityTransform(); var parentTransform = (parent != null) ? parent.computedTransform : tileset.GetRootTransform(); this.computedTransform = parentTransform * this.transform; this.BoundingVolume = CreateBoundingVolume(tile.BoundingVolume, this.computedTransform); // TODO: Add 2D bounding volumes if (tile.Content != null && tile.Content.BoundingVolume.IsDefined()) { // Non-leaf tiles may have a content bounding-volume, which is a tight-fit bounding volume // around only the features in the tile. This box is useful for culling for rendering, // but not for culling for traversing the tree since it does not guarantee spatial coherence, i.e., // since it only bounds features in the tile, not the entire tile, children may be // outside of this box. this.ContentBoundingVolume = CreateBoundingVolume(tile.Content.BoundingVolume, this.computedTransform); } else { // Default to tile bounding volume this.ContentBoundingVolume = CreateBoundingVolume(tile.BoundingVolume, this.computedTransform); } // TODO: Add viewer request volume support //if(tile.ViewerRequestVolume != null && tile.ViewerRequestVolume.IsDefined()) //{ // this.viewerRequestVolume = CreateBoundingVolume(tile.ViewerRequestVolume, transform); //} if (!tile.Refine.HasValue) { tile.Refine = (parent == null) ? Schema.TileRefine.REPLACE : parent.tile.Refine.Value; } this.Parent = parent; if (this.HasEmptyContent) { this.ContentState = Unity3DTileContentState.READY; } else { ContentState = Unity3DTileContentState.UNLOADED; this.ContentUrl = UrlUtils.JoinUrls(basePath, tile.Content.GetUri()); } this.HasRenderableContent = false; this.HasTilesetContent = false; }
/// <summary> /// Lower priority will be loaded sooner /// </summary> /// <param name="priority"></param> public void RequestContent(float priority) { if (this.Tileset.RequestManager.Full()) { return; } if (this.HasEmptyContent) { return; } if (this.ContentState == Unity3DTileContentState.UNLOADED || this.ContentState == Unity3DTileContentState.EXPIRED) { this.ContentState = Unity3DTileContentState.LOADING; Promise <bool> finished = new Promise <bool>(); finished.Then((success) => { this.Tileset.Statistics.NetworkError = !success; this.Tileset.Statistics.RequestsThisFrame += 1; if (success) { this.ContentState = Unity3DTileContentState.PROCESSING; this.Content.SetShadowMode(this.Tileset.TilesetOptions.ShadowCastingMode, this.Tileset.TilesetOptions.RecieveShadows); this.Tileset.Statistics.LoadedContentCount += 1; this.Tileset.Statistics.TotalTilesLoaded += 1; // Track tile in cache as soon as it has downloaded content, but still queue it for processing CacheRequestStatus status = this.Tileset.LRUContent.Add(this); if (status == CacheRequestStatus.ADDED) { this.Tileset.ProcessingQueue.Enqueue(this); } else { UnloadContent(); } } else { UnloadContent(); } }); Promise started = new Promise(); started.Then(() => { GameObject go = new GameObject(Id); go.transform.parent = this.Tileset.Behaviour.transform; go.transform.localPosition = new Vector3(this.computedTransform.m03, this.computedTransform.m13, this.computedTransform.m23); go.transform.localRotation = this.computedTransform.rotation; go.transform.localScale = this.computedTransform.lossyScale; go.layer = this.Tileset.Behaviour.gameObject.layer; go.SetActive(false); var info = go.AddComponent <TileInfo>(); info.Tile = this; this.Content = new Unity3DTileContent(go); if (ContentType == Unity3DTileContentType.B3DM) { B3DMComponent b3dmCo = go.AddComponent <B3DMComponent>(); b3dmCo.Url = this.ContentUrl; b3dmCo.Multithreaded = this.Tileset.TilesetOptions.GLTFMultithreadedLoad; b3dmCo.MaximumLod = this.Tileset.TilesetOptions.GLTFMaximumLOD; if (!string.IsNullOrEmpty(this.Tileset.TilesetOptions.ShaderOverride)) { b3dmCo.ShaderOverride = Shader.Find(this.Tileset.TilesetOptions.ShaderOverride); } b3dmCo.AddColliders = false; b3dmCo.DownloadOnStart = false; this.Tileset.Behaviour.StartCoroutine(b3dmCo.Download(finished)); } else if (ContentType == Unity3DTileContentType.PNTS) { PNTSComponent pntsCo = go.AddComponent <PNTSComponent>(); pntsCo.Url = UrlUtils.RemoveQuery(this.ContentUrl); pntsCo.ShaderOverride = Shader.Find("Point Cloud/Point"); pntsCo.DownloadOnStart = false; this.Tileset.Behaviour.StartCoroutine(pntsCo.Download(finished)); } }); Request request = new Request(this, priority, started, finished); this.Tileset.RequestManager.EnqueRequest(request); } }
public static IEnumerator Load(IndexMode mode, string tileUrl, Action <Unity3DTileIndex> success, Action <IndexMode, string, string> fail) { if (mode == IndexMode.Default || mode == IndexMode.None) { success(null); yield break; } string url = UrlUtils.ReplaceDataProtocol(tileUrl); string dir = UrlUtils.GetBaseUri(tileUrl); string file = UrlUtils.GetLastPathSegment(tileUrl); var filesToTry = new Queue <string>(); if (mode == IndexMode.ExternalPNG) { filesToTry.Enqueue(UrlUtils.StripUrlExtension(file) + "_index.png"); filesToTry.Enqueue(UrlUtils.ChangeUrlExtension(file, ".png")); } else if (mode == IndexMode.ExternalPPM) { filesToTry.Enqueue(UrlUtils.StripUrlExtension(file) + "_index.ppm"); filesToTry.Enqueue(UrlUtils.ChangeUrlExtension(file, ".ppm")); } else if (mode == IndexMode.ExternalPPMZ) { filesToTry.Enqueue(UrlUtils.StripUrlExtension(file) + "_index.ppmz"); filesToTry.Enqueue(UrlUtils.ChangeUrlExtension(file, ".ppmz")); } else { filesToTry.Enqueue(file); } Stream stream = null; Exception exception = null; string ext = null; while (stream == null && filesToTry.Count > 0) { exception = null; IEnumerator enumerator = null; ILoader loader = null; try { file = filesToTry.Dequeue(); ext = UrlUtils.GetUrlExtension(file).ToLower(); loader = AbstractWebRequestLoader.CreateDefaultRequestLoader(dir); if (ext == ".b3dm") { loader = new B3DMLoader(loader); } //yield return loader.LoadStream(file); //works but can't catch exceptions enumerator = loader.LoadStream(file); } catch (Exception ex) { exception = ex; } while (exception == null) { try { if (!enumerator.MoveNext()) { break; } } catch (Exception ex) { exception = ex; break; } yield return(enumerator.Current); } if (exception == null && loader.LoadedStream != null && loader.LoadedStream.Length > 0) { stream = loader.LoadedStream; stream.Seek(0, SeekOrigin.Begin); } } if (stream == null || stream.Length == 0) { fail(mode, tileUrl, "download failed" + (exception != null ? (" " + exception.Message) : "")); yield break; } try { if (ext == ".b3dm" || ext == ".glb") { success(LoadFromGLB(stream)); } else if (ext == ".gltf") { success(LoadFromGLTF(stream)); } else if (ext == ".png") { success(LoadFromPNG(stream)); } else if (ext == ".ppm" || ext == ".ppmz") { success(LoadFromPPM(stream, compressed: ext == ".ppmz")); } else { fail(mode, tileUrl, "unhandled file type: " + ext); } } catch (Exception ex) { fail(mode, tileUrl, "failed to parse " + file + ": " + ex.Message + "\n" + ex.StackTrace); } }