private void FailGetGeometryBufferRequest(LoadCubeRequest loadRequest, string modelPath) { CheckIfBackgroundThread(); loadRequest.Failures++; lock (_eboCache) { // Remove the 'in progress' marker from the cache _eboCache.Remove(modelPath); } if (RETRY_LIMIT > loadRequest.Failures) { Debug.LogError("Retry limit hit for: " + modelPath); Debug.LogError("Cube load failed for " + loadRequest); // Let another depenent cube try lock (_dependentCubes) { LinkedList <LoadCubeRequest> dependentRequests; if (_dependentCubes.TryGetValue(modelPath, out dependentRequests)) { var request = dependentRequests.Last.Value; dependentRequests.RemoveLast(); _loadGeometryBufferQueue.ConcurrentEnqueue(request).Wait(); } } } else { // Queue for retry _loadGeometryBufferQueue.ConcurrentEnqueue(loadRequest).Wait(); } }
private void CancelRequest() { if (_loadCubeRequest != null) { _loadCubeRequest.Cancelled = true; _loadCubeRequest = null; } }
private IEnumerator RequestCubeLoad() { CancelRequest(); _loadCubeRequest = new LoadCubeRequest(_x, _y, _z, _lodIndex, _pyriteQuery, createdObject => { DestroyChildren(); _cubes.Add(createdObject); StartCoroutine(StopRenderCheck(Camera.main)); }); return(_manager.EnqueueLoadCubeRequest(_loadCubeRequest)); }
private IEnumerator BuildCubeRequest(LoadCubeRequest loadRequest) { Build( loadRequest.GeometryBuffer, loadRequest.MaterialData, loadRequest.X, loadRequest.Y, loadRequest.Z, loadRequest.LodIndex, loadRequest.gameObject); yield break; }
void RequestCube(int X, int Y, int Z, int detailLevel, GameObject refObj) { if (HideModelMesh) { return; } //var loadRequest = new LoadCubeRequest(X, Y, Z, detailLevel, pyriteQuery, cubeObj => { refObj = cubeObj; }); var loadRequest = new LoadCubeRequest(X, Y, Z, detailLevel, refObj); StartCoroutine(EnqueueLoadCubeRequest(loadRequest)); }
private IEnumerator AddDependentRequest(LoadCubeRequest dependentRequest, string dependencyKey) { // Model is in the process of being constructed. Add request to dependency list while (!Monitor.TryEnter(_dependentCubes)) { yield return(null); } LinkedList <LoadCubeRequest> dependentRequests; if (!_dependentCubes.TryGetValue(dependencyKey, out dependentRequests)) { dependentRequests = new LinkedList <LoadCubeRequest>(); _dependentCubes.Add(dependencyKey, dependentRequests); } dependentRequests.AddLast(dependentRequest); Monitor.Exit(_dependentCubes); }
// Determine the next appropriate queue for the request private void MoveRequestForward(LoadCubeRequest loadRequest) { #if !UNITY_WSA var onMainThread = _mainThread.Equals(Thread.CurrentThread); #else // Can't check for UIThread yet on Windows Store Apps so assume we are not (trying to StartCoroutine will fail otherwise) var onMainThread = false; #endif if (loadRequest.GeometryBuffer == null) { if (onMainThread) { StartCoroutine(_loadGeometryBufferQueue.ConcurrentEnqueue(loadRequest)); } else { _loadGeometryBufferQueue.ConcurrentEnqueue(loadRequest).Wait(); } } else if (loadRequest.MaterialData == null) { if (onMainThread) { StartCoroutine(_loadMaterialQueue.ConcurrentEnqueue(loadRequest)); } else { _loadMaterialQueue.ConcurrentEnqueue(loadRequest).Wait(); } } else { if (onMainThread) { StartCoroutine(_buildCubeRequests.ConcurrentEnqueue(loadRequest)); } else { _buildCubeRequests.ConcurrentEnqueue(loadRequest).Wait(); } } }
private void MoveRequestForward(LoadCubeRequest loadRequest) { #if !UNITY_WSA var onMainThread = _mainThread.Equals(Thread.CurrentThread); #else var onMainThread = false; #endif if (loadRequest.GeometryBuffer == null) { if (onMainThread) { StartCoroutine(_loadGeometryBufferQueue.ConcurrentEnqueue(loadRequest)); } else { _loadGeometryBufferQueue.ConcurrentEnqueue(loadRequest).Wait(); } } else if (loadRequest.MaterialData == null) { if (onMainThread) { StartCoroutine(_loadMaterialQueue.ConcurrentEnqueue(loadRequest)); } else { _loadMaterialQueue.ConcurrentEnqueue(loadRequest).Wait(); } } else { if (onMainThread) { StartCoroutine(_buildCubeRequests.ConcurrentEnqueue(loadRequest)); } else { _buildCubeRequests.ConcurrentEnqueue(loadRequest).Wait(); } } }
private IEnumerator GetModelForRequest(LoadCubeRequest loadRequest) { //var modelPath = loadRequest.Query.GetModelPath(loadRequest.LodIndex, loadRequest.X, loadRequest.Y, loadRequest.Z); var modelPath = pyriteQuery.GetModelPath(loadRequest.LodIndex, loadRequest.X, loadRequest.Y, loadRequest.Z); while (!Monitor.TryEnter(_eboCache)) { yield return(null); } // If the geometry data is being loaded or this is the first request to load it add the request the dependency list if (!_eboCache.ContainsKey(modelPath) || _eboCache[modelPath] == null) { yield return(StartCoroutine(AddDependentRequest(loadRequest, modelPath))); if (!_eboCache.ContainsKey(modelPath)) { // Model data was not present in cache nor has any request started constructing it //EboCacheMisses++; _eboCache[modelPath] = null; if (UseWwwForEbo) { var cachePath = CacheWebRequest.GetCacheFilePath(modelPath); WWW modelWww; if (CacheWebRequest.IsItemInCache(cachePath)) { //FileCacheHits++; modelWww = new WWW("file:///" + cachePath); yield return(modelWww); } else { //FileCacheMisses++; modelWww = new WWW(modelPath); yield return(modelWww); CacheWebRequest.AddToCache(cachePath, modelWww.bytes); } GeometryBuffer buffer = new GeometryBuffer(_geometryBufferAltitudeTransform, true) { Buffer = modelWww.bytes }; buffer.Process(); _eboCache[modelPath] = buffer; yield return(StartCoroutine(SucceedGetGeometryBufferRequest(modelPath, buffer))); } else { CacheWebRequest.GetBytes(modelPath, modelResponse => { lock (_eboCache) { if (modelResponse.Status == CacheWebRequest.CacheWebResponseStatus.Error) { Debug.LogError("Error getting model [" + modelPath + "] " + modelResponse.ErrorMessage); FailGetGeometryBufferRequest(loadRequest, modelPath); } else if (modelResponse.Status == CacheWebRequest.CacheWebResponseStatus.Cancelled) { _eboCache.Remove(modelPath); } else { if (modelResponse.IsCacheHit) { //FileCacheHits++; } else { //FileCacheMisses++; } GeometryBuffer buffer = new GeometryBuffer(_geometryBufferAltitudeTransform, true) { Buffer = modelResponse.Content }; buffer.Process(); _eboCache[modelPath] = buffer; SucceedGetGeometryBufferRequest(modelPath, buffer).Wait(); } } }, DependentRequestsExistBlocking); } } } else // The model data was in the cache { // Model was constructed move request to next step //EboCacheHits++; loadRequest.GeometryBuffer = _eboCache[modelPath]; MoveRequestForward(loadRequest); } Monitor.Exit(_eboCache); }
private IEnumerator GetMaterialForRequest(LoadCubeRequest loadRequest) { //var pyriteLevel = loadRequest.Query.DetailLevels[loadRequest.LodIndex]; //var textureCoordinates = pyriteLevel.TextureCoordinatesForCube(loadRequest.X, loadRequest.Y); //var texturePath = loadRequest.Query.GetTexturePath(loadRequest.LodIndex, (int)textureCoordinates.x, (int)textureCoordinates.y); var pyriteLevel = pyriteQuery.DetailLevels[loadRequest.LodIndex]; var textureCoordinates = pyriteLevel.TextureCoordinatesForCube(loadRequest.X, loadRequest.Y); var texturePath = pyriteQuery.GetTexturePath(loadRequest.LodIndex, (int)textureCoordinates.x, (int)textureCoordinates.y); while (!Monitor.TryEnter(MaterialDataCache)) { yield return(null); } // If the material data is not in the cache or in the middle of being constructed add this request as a dependency if (!MaterialDataCache.ContainsKey(texturePath) || MaterialDataCache[texturePath] == null) { // Add this request to list of requests that is waiting for the data yield return(StartCoroutine(AddDependentRequest(loadRequest, texturePath))); // Check if this is the first request for material (or it isn't in the cache) if (!MaterialDataCache.ContainsKey(texturePath)) { if (UseWwwForTextures) { // Material data was not in cache nor being constructed // Set to null to signal to other tasks that the key is in the process // of being filled MaterialDataCache[texturePath] = null; var materialData = CubeBuilderHelpers.GetDefaultMaterialData( (int)textureCoordinates.x, (int)textureCoordinates.y, loadRequest.LodIndex, texturePath); var cachePath = CacheWebRequest.GetCacheFilePath(texturePath); if (!CacheFill) { WWW textureWww; // = new WWW(texturePath); if (CacheWebRequest.IsItemInCache(cachePath)) { textureWww = new WWW("file:///" + cachePath); yield return(textureWww); } else { textureWww = new WWW(texturePath); yield return(textureWww); CacheWebRequest.AddToCache(cachePath, textureWww.bytes); } materialData.DiffuseTex = textureWww.texture; materialData.DiffuseTex.name = materialData.Name; } MaterialDataCache[texturePath] = materialData; MaterialDataCache.AddRef(texturePath); // Move forward dependent requests that wanted this material data yield return(StartCoroutine(SucceedGetMaterialDataRequests(texturePath, materialData))); } else { // Material data was not in cache nor being constructed // Set to null to signal to other tasks that the key is in the process // of being filled MaterialDataCache[texturePath] = null; var materialData = CubeBuilderHelpers.GetDefaultMaterialData( (int)textureCoordinates.x, (int)textureCoordinates.y, loadRequest.LodIndex, texturePath); _partiallyConstructedMaterialDatas[texturePath] = materialData; CacheWebRequest.GetBytes(texturePath, textureResponse => { CheckIfBackgroundThread(); if (textureResponse.Status == CacheWebRequest.CacheWebResponseStatus.Error) { Debug.LogError("Error getting texture [" + texturePath + "] " + textureResponse.ErrorMessage); FailGetMaterialDataRequest(loadRequest, texturePath); } else if (textureResponse.Status == CacheWebRequest.CacheWebResponseStatus.Cancelled) { lock (MaterialDataCache) { MaterialDataCache.Remove(texturePath); } } else { if (textureResponse.IsCacheHit) { //FileCacheHits++; } else { //FileCacheMisses++; } _texturesReadyForMaterialDataConstruction.ConcurrentEnqueue( new KeyValuePair <string, byte[]>(texturePath, textureResponse.Content)).Wait(); } }, DependentRequestsExistBlocking); } } } else // The material was in the cache { // Material data ready get it and move on //MaterialCacheHits++; loadRequest.MaterialData = MaterialDataCache[texturePath]; MaterialDataCache.AddRef(texturePath); MoveRequestForward(loadRequest); } Monitor.Exit(MaterialDataCache); }
public IEnumerator EnqueueLoadCubeRequest(LoadCubeRequest loadRequest) { yield return(StartCoroutine(_loadMaterialQueue.ConcurrentEnqueue(loadRequest))); }
protected virtual IEnumerator Load() { _pyriteQuery = new PyriteQuery(this, SetName, ModelVersion, PyriteServer, UpgradeFactor, UpgradeConstant, DowngradeFactor, DowngradeConstant); yield return(StartCoroutine(_pyriteQuery.LoadAll(FilterDetailLevels ? DetailLevelsToFilter : null))); var initialDetailLevelIndex = DetailLevel - 1; if (UseCameraDetection) { initialDetailLevelIndex = _pyriteQuery.DetailLevels.Length - 1; } _pyriteLevel = _pyriteQuery.DetailLevels[initialDetailLevelIndex]; var allOctCubes = _pyriteQuery.DetailLevels[initialDetailLevelIndex].Octree.AllItems(); foreach (var octCube in allOctCubes) { var pCube = CreateCubeFromCubeBounds(octCube); var x = pCube.X; var y = pCube.Y; var z = pCube.Z; var cubePos = _pyriteLevel.GetWorldCoordinatesForCube(pCube); _geometryBufferAltitudeTransform = 0 - _pyriteLevel.ModelBoundsMin.z; if (UseCameraDetection) { var detectionCube = ObjectPooler.Current.GetPooledObject(PlaceHolderCube); detectionCube.transform.position = new Vector3(-cubePos.x, cubePos.z + _geometryBufferAltitudeTransform, -cubePos.y); detectionCube.transform.rotation = Quaternion.identity; var meshRenderer = detectionCube.GetComponent <MeshRenderer>(); meshRenderer.enabled = true; detectionCube.GetComponent <IsRendered>() .SetCubePosition(x, y, z, initialDetailLevelIndex, _pyriteQuery, this); detectionCube.transform.localScale = new Vector3( _pyriteLevel.WorldCubeScale.x, _pyriteLevel.WorldCubeScale.z, _pyriteLevel.WorldCubeScale.y); detectionCube.SetActive(true); } else { var loadRequest = new LoadCubeRequest(x, y, z, initialDetailLevelIndex, _pyriteQuery, null); yield return(StartCoroutine(EnqueueLoadCubeRequest(loadRequest))); } } if (CameraRig != null) { // Hardcodes the coordinate inversions which are parameterized on the geometry buffer var min = new Vector3( -_pyriteLevel.ModelBoundsMin.x, _pyriteLevel.ModelBoundsMin.z + _geometryBufferAltitudeTransform, -_pyriteLevel.ModelBoundsMin.y); var max = new Vector3( -_pyriteLevel.ModelBoundsMax.x, _pyriteLevel.ModelBoundsMax.z + _geometryBufferAltitudeTransform, -_pyriteLevel.ModelBoundsMax.y); //Kainiemi: Some mechanism needed to inform InputManager about the transform change var inputManager = CameraRig.GetComponent <PyriteDemoClient.InputManager>(); if (inputManager != null) { // Give input manager position limits based on model bounds var highestLod = _pyriteQuery.DetailLevels.First(); var lowestLod = _pyriteQuery.DetailLevels.Last(); inputManager.SetInputLimits( new Vector3(highestLod.ModelBoundsMin.x + lowestLod.WorldCubeScale.x / 2, highestLod.ModelBoundsMin.z + _geometryBufferAltitudeTransform + lowestLod.WorldCubeScale.z / 3, highestLod.ModelBoundsMin.y + lowestLod.WorldCubeScale.y / 2), new Vector3(highestLod.ModelBoundsMax.x - lowestLod.WorldCubeScale.x / 2, highestLod.ModelBoundsMax.z + _geometryBufferAltitudeTransform + (lowestLod.WorldCubeScale.z * 1.5f), highestLod.ModelBoundsMax.y - lowestLod.WorldCubeScale.y / 2)); if (AutomateCameraPositionOnLoad) { var newCameraPosition = min + (max - min) / 1.5f; newCameraPosition += new Vector3(0, (max - min).y * 2f, 0); CameraRig.transform.position = newCameraPosition; inputManager.NotifyOnTransformChange(CameraRig.transform.position); } else { inputManager.NotifyReadyForControl(); } } } }
// Used to create a and populate a game object for this request private IEnumerator BuildCubeRequest(LoadCubeRequest loadRequest) { Build(loadRequest.GeometryBuffer, loadRequest.MaterialData, loadRequest.X, loadRequest.Y, loadRequest.Z, loadRequest.Query.DetailLevels[loadRequest.LodIndex].Value, loadRequest.RegisterCreatedObjects); yield break; }
protected override IEnumerator Load() { var pyriteQuery = new PyriteQuery(this, SetName, ModelVersion, PyriteServer); if (TargetGameObject != null) { var transformedPosition = new Vector3( -TargetGameObject.transform.position.x, -TargetGameObject.transform.position.z, TargetGameObject.transform.position.y - 600 ); yield return(StartCoroutine(pyriteQuery.Load3X3(Reference, transformedPosition))); } else { yield return(StartCoroutine(pyriteQuery.Load3X3(Reference, QueryPosition))); } var xmin = pyriteQuery.DetailLevels[0].WorldBoundsMax.x; var ymin = pyriteQuery.DetailLevels[0].WorldBoundsMax.y; var zmin = pyriteQuery.DetailLevels[0].WorldBoundsMax.z; var xmax = pyriteQuery.DetailLevels[0].WorldBoundsMin.x; var ymax = pyriteQuery.DetailLevels[0].WorldBoundsMin.y; var zmax = pyriteQuery.DetailLevels[0].WorldBoundsMin.z; var cubesToSkip = new Dictionary <int, HashSet <PyriteCube> >(); foreach (var pyriteLevel in pyriteQuery.DetailLevels) { xmin = pyriteLevel.WorldBoundsMax.x; ymin = pyriteLevel.WorldBoundsMax.y; zmin = pyriteLevel.WorldBoundsMax.z; xmax = pyriteLevel.WorldBoundsMin.x; ymax = pyriteLevel.WorldBoundsMin.y; zmax = pyriteLevel.WorldBoundsMin.z; cubesToSkip[pyriteLevel.Value + 1] = new HashSet <PyriteCube>(); if (!cubesToSkip.ContainsKey(pyriteLevel.Value)) { cubesToSkip[pyriteLevel.Value] = new HashSet <PyriteCube>(); } for (var i = 0; i < pyriteLevel.Cubes.Length; i++) { var x = pyriteLevel.Cubes[i].X; var y = pyriteLevel.Cubes[i].Y; var z = pyriteLevel.Cubes[i].Z; var cubeFactor = pyriteQuery.GetPreviousCubeFactor(pyriteLevel.Value - 1); cubesToSkip[pyriteLevel.Value + 1].Add(new PyriteCube { X = x / (int)cubeFactor.x, Y = y / (int)cubeFactor.y, Z = z / (int)cubeFactor.z }); if (cubesToSkip[pyriteLevel.Value].Contains(new PyriteCube { X = x, Y = y, Z = z })) { if (SkipLowerDetailedCubes) { continue; } } var cubePos = pyriteLevel.GetWorldCoordinatesForCube(pyriteLevel.Cubes[i]); xmin = Math.Min(cubePos.x, xmin); ymin = Math.Min(cubePos.y, ymin); zmin = Math.Min(cubePos.z, zmin); xmax = Math.Max(cubePos.x, xmax); ymax = Math.Max(cubePos.y, ymax); zmax = Math.Max(cubePos.z, zmax); var loadRequest = new LoadCubeRequest(x, y, z, pyriteLevel.Value - 1, pyriteQuery, null); yield return(StartCoroutine(EnqueueLoadCubeRequest(loadRequest))); } } if (CameraRig != null) { // Hardcoding some values for now var min = new Vector3(xmin, ymin, zmin); var max = new Vector3(xmax, ymax, zmax); var newCameraPosition = min + (max - min) / 2.0f; newCameraPosition += new Vector3(0, 0, (max - min).z * 1.4f); CameraRig.transform.position = newCameraPosition; CameraRig.transform.rotation = Quaternion.Euler(0, 180, 0); } }