/// <summary> /// Fill out and dispatch a surface baking request. /// </summary> /// <param name="bestSurface">Info for the surface to bake.</param> private void DispatchBakeRequest(SurfaceEntry bestSurface) { SurfaceData sd; sd.id.handle = bestSurface.handle; sd.outputMesh = bestSurface.surfaceObject.GetComponent <MeshFilter>(); // The WorldAnchor has been put on a generated child of the surface object. sd.outputAnchor = bestSurface.worldAnchorChild.GetComponent <WorldAnchor>(); sd.outputCollider = bestSurface.surfaceObject.GetComponent <MeshCollider>(); sd.trianglesPerCubicMeter = TrianglesPerCubicMeter; sd.bakeCollider = Collide; try { if (observer.RequestMeshAsync(sd, SurfaceDataReadyHandler)) { waitingForBake = true; } else { // A return value of false when requesting meshes // typically indicates that the specified Surface handle is invalid. Debug.Log($"Bake request for {bestSurface.handle} failed, invalid parameters suspected"); } } catch { Debug.Log($"Bake for surface {bestSurface.handle} failed unexpectedly!"); } }
} // villsa #endregion #region ================== Constructor / Disposer // Constructor internal Sector(MapSet map, int listindex, int index) { // Initialize this.map = map; this.listindex = listindex; this.sidedefs = new LinkedList <Sidedef>(); this.fixedindex = index; this.floortexname = "-"; this.ceiltexname = "-"; this.longfloortexname = MapSet.EmptyLongName; this.longceiltexname = MapSet.EmptyLongName; this.updateneeded = true; this.triangulationneeded = true; this.surfaceentry = new SurfaceEntry(-1, -1, -1); this.flags = new Dictionary <string, bool>(); // villsa this.ceilColor = new Lights(128, 128, 128, 0); // villsa this.flrColor = new Lights(128, 128, 128, 0); // villsa this.thingColor = new Lights(128, 128, 128, 0); // villsa this.topColor = new Lights(128, 128, 128, 0); // villsa this.lwrColor = new Lights(128, 128, 128, 0); // villsa if (map == General.Map.Map) { General.Map.UndoRedo.RecAddSector(this); } // We have no destructor GC.SuppressFinalize(this); }
private SurfaceEntry FindBestSurfaceToBake() { // Prioritize older adds over other adds over updates. SurfaceEntry bestSurface = null; foreach (var surface in surfaces.Values) { if (surface.currentState != BakedState.Baked) { if (bestSurface == null) { bestSurface = surface; } else { if (surface.currentState < bestSurface.currentState) { bestSurface = surface; } else if (surface.updateTime < bestSurface.updateTime) { bestSurface = surface; } } } } return(bestSurface); }
void onSurfaceChanged(SurfaceId id, SurfaceChange changeType, Bounds bounds, DateTime updateTime) { if (changeType == SurfaceChange.Added) { SurfaceEntry newEntry = new SurfaceEntry(id.handle, bounds, renderMeshes, meshMaterial); newEntry.gameObject.transform.parent = gameObject.transform; surfaces.Add(id.handle, newEntry); } if (changeType == SurfaceChange.Added || changeType == SurfaceChange.Updated) { // queue for baking SurfaceEntry surface; if (surfaces.TryGetValue(id.handle, out surface)) { bakingQueue.Add(surface); } } if (changeType == SurfaceChange.Removed) { surfaces.Remove(id.handle); } }
// This handler receives surface changed events and is propagated by the // Update method on SurfaceObserver. void SurfaceChangedHandler(SurfaceId id, SurfaceChange changeType, Bounds bounds, DateTime updateTime) { SurfaceEntry entry; switch (changeType) { case SurfaceChange.Added: case SurfaceChange.Updated: if (m_Surfaces.TryGetValue(id.handle, out entry)) { // If this surface has already been baked, mark it as needing bake // in addition to the update time so the "next surface to bake" // logic will order it correctly. if (entry.m_BakedState == BakedState.Baked) { entry.m_BakedState = BakedState.UpdatePostBake; entry.m_UpdateTime = updateTime; } } else { // This is a brand new surface so create an entry for it. entry = new SurfaceEntry(); entry.m_BakedState = BakedState.NeverBaked; entry.m_UpdateTime = updateTime; entry.m_Id = id.handle; entry.m_Surface = new GameObject(System.String.Format("Surface-{0}", id.handle)); //SetActive(isRendering); entry.m_Surface.AddComponent <MeshFilter>(); entry.m_Surface.AddComponent <MeshCollider>(); MeshRenderer mr = entry.m_Surface.AddComponent <MeshRenderer>(); mr.shadowCastingMode = ShadowCastingMode.Off; mr.receiveShadows = false; entry.m_Surface.AddComponent <WorldAnchor>(); entry.m_Surface.GetComponent <MeshRenderer>().sharedMaterial = m_drawMat; entry.m_Surface.GetComponent <MeshRenderer>().enabled = isRendering; m_Surfaces[id.handle] = entry; if (!SurfacesList.Contains(entry)) { SurfacesList.Add(entry); } } break; case SurfaceChange.Removed: if (m_Surfaces.TryGetValue(id.handle, out entry)) { m_Surfaces.Remove(id.handle); Mesh mesh = entry.m_Surface.GetComponent <MeshFilter>().mesh; if (mesh) { Destroy(mesh); } Destroy(entry.m_Surface); } break; } }
private void UpdateSurfaces() { if (waitingForBake) { return; } SurfaceEntry bestSurface = FindBestSurfaceToBake(); if (bestSurface != null) { DispatchBakeRequest(bestSurface); } }
private void FixedUpdate() { if (lastMeshDownlinkTime + 5.0f < Time.realtimeSinceStartup) { /* * List meshFilters = SpatialMappingManager.Instance.GetMeshFilters(); * * for (int i = 0; i < meshFilters.Count; i++) * { * NetworkMeshSource.getSingleton().sendMesh(meshFilters[i].mesh, * meshFilters[i].gameObject.transform.position, * meshFilters[i].gameObject.transform.rotation); * * * }*/ for (int index = 0; index < SurfacesList.Count; index++) { SurfaceEntry item = SurfacesList[index]; //if(item.m_BakedState== BakedState.Baked) //{ GameObject go = item.m_Surface; if (go) { MeshFilter MFer = go.GetComponent <MeshFilter>(); if (MFer) { Mesh meesh = MFer.mesh; if (meesh) { NetworkMeshSource.getSingleton().sendMesh(meesh, go.transform.position, go.transform.rotation); } } } //} } lastMeshDownlinkTime = Time.realtimeSinceStartup; } }
private void FixedUpdate() { if (lastMeshDownlinkTime + 10.0f < Time.realtimeSinceStartup) { // you can't block here and wait for the camera capture. // Send the old data and trigger a new capture. // NetworkMeshSource.getSingleton() for (int index = 0; index < SurfacesList.Count; index++) { SurfaceEntry item = SurfacesList[index]; if (item.m_BakedState == BakedState.Baked || item.m_BakedState == BakedState.UpdatePostBake) { GameObject go = item.m_Surface; if (go) { MeshFilter[] meshFilters = go.GetComponents <MeshFilter>(); for (int mfi = 0; mfi < meshFilters.Length; mfi++) { MeshFilter MFer = meshFilters[mfi]; if (MFer) { Mesh meesh = MFer.mesh; if (meesh && meesh.triangles.Length > 0) { #if !UNITY_EDITOR NetworkMeshSource.getSingleton().sendMesh(meesh, go.transform.position, go.transform.rotation); #endif } } } } } } lastMeshDownlinkTime = Time.realtimeSinceStartup; } }
// This updates the ceiling surface public void UpdateCeilingSurface() { if (flatvertices == null) { return; } // Create ceiling vertices FlatVertex[] ceilvertices = new FlatVertex[flatvertices.Length]; flatvertices.CopyTo(ceilvertices, 0); General.Plugins.OnSectorCeilingSurfaceUpdate(this, ref ceilvertices); surfaceentry.ceilvertices = ceilvertices; surfaceentry.ceiltexture = longceiltexname; if (surfaceentry.floorvertices == null) { surfaceentry.floorvertices = ceilvertices; } // Update entry surfaceentry = General.Map.CRenderer2D.Surfaces.UpdateSurfaces(surfaceentry); General.Map.CRenderer2D.Surfaces.UnlockBuffers(); }
void Update() { // Avoid calling Update on a SurfaceObserver too frequently. if (m_lastUpdateTime + 5.0f < Time.realtimeSinceStartup) { // This block makes the observation volume follow the camera. Vector3 extents; extents.x = SurfaceEntry.c_Extents * 8.0f; extents.y = SurfaceEntry.c_Extents * 8.0f; extents.z = SurfaceEntry.c_Extents * 8.0f; m_Observer.SetVolumeAsAxisAlignedBox(Camera.main.transform.position, extents); try { m_Observer.Update(SurfaceChangedHandler); } catch { // Update can throw an exception if the specified callback was bad. Debug.Log("Observer update failed unexpectedly!"); } m_lastUpdateTime = Time.realtimeSinceStartup; } if (!m_WaitingForBake) { // Prioritize older adds over other adds over updates. SurfaceEntry bestSurface = null; foreach (KeyValuePair <int, SurfaceEntry> surface in m_Surfaces) { if (surface.Value.m_BakedState != BakedState.Baked) { if (bestSurface == null) { bestSurface = surface.Value; } else { if (surface.Value.m_BakedState < bestSurface.m_BakedState) { bestSurface = surface.Value; } else if (surface.Value.m_UpdateTime < bestSurface.m_UpdateTime) { bestSurface = surface.Value; } } } } if (bestSurface != null) { // Fill out and dispatch the request. SurfaceData sd; sd.id.handle = bestSurface.m_Id; sd.outputMesh = bestSurface.m_Surface.GetComponent <MeshFilter>(); sd.outputAnchor = bestSurface.m_Surface.GetComponent <WorldAnchor>(); sd.outputCollider = bestSurface.m_Surface.GetComponent <MeshCollider>(); sd.trianglesPerCubicMeter = 500.0f; sd.bakeCollider = true; try { if (m_Observer.RequestMeshAsync(sd, SurfaceDataReadyHandler)) { m_WaitingForBake = true; } else { // A return value of false when requesting meshes // typically indicates that the specified surface // ID specified was invalid. Debug.Log(System.String.Format("Bake request for {0} failed. Is {0} a valid Surface ID?", bestSurface.m_Id)); } } catch { // Requests can fail if the data struct is not filled out // properly. Debug.Log(System.String.Format("Bake for id {0} failed unexpectedly!", bestSurface.m_Id)); } } } }
/// <summary> /// This handler receives events when surfaces change, and propagates those events /// using the SurfaceObserver’s Update method /// </summary> /// <param name="id">Handle identifying the surface</param> /// <param name="changeType">Reason for update</param> /// <param name="bounds">New bounds of th esurface</param> /// <param name="updateTime">Time stamp of modification.</param> private void SurfaceChangedHandler(SurfaceId id, SurfaceChange changeType, Bounds bounds, DateTime updateTime) { SurfaceEntry entry; switch (changeType) { case SurfaceChange.Added: case SurfaceChange.Updated: if (surfaces.TryGetValue(id.handle, out entry)) { // If the system has already baked this Surface, lower its priority. if (entry.currentState == BakedState.Baked) { entry.currentState = BakedState.UpdatePostBake; entry.updateTime = updateTime; } } else { // This is a brand new Surface so create an entry for it. entry = new SurfaceEntry(); entry.currentState = BakedState.NeverBaked; entry.updateTime = updateTime; entry.handle = id.handle; entry.surfaceObject = new GameObject(System.String.Format("Surface-{0}", id.handle)); entry.surfaceObject.layer = spatialMappingLayer; if (HangerObject != null) { entry.surfaceObject.transform.SetParent(HangerObject, false); } entry.surfaceObject.AddComponent <MeshFilter>(); if (Collide) { entry.surfaceObject.AddComponent <MeshCollider>(); } MeshRenderer mr = entry.surfaceObject.AddComponent <MeshRenderer>(); mr.shadowCastingMode = ShadowCastingMode.Off; mr.receiveShadows = false; mr.sharedMaterial = DrawMaterial; mr.enabled = this.Display; entry.worldAnchorChild = new GameObject(entry.surfaceObject.name + "WorldAnchor"); entry.worldAnchorChild.transform.SetParent(entry.surfaceObject.transform, false); entry.worldAnchorChild.AddComponent <WorldAnchor>(); // Add an adapter component to keep the surface object where the WorldAnchor means it to be. var adapter = entry.surfaceObject.AddComponent <WorldAnchorAdapter>(); adapter.TargetObject = entry.surfaceObject.transform; adapter.WorldAnchorObject = entry.worldAnchorChild; surfaces[id.handle] = entry; } break; case SurfaceChange.Removed: if (surfaces.TryGetValue(id.handle, out entry)) { surfaces.Remove(id.handle); Destroy(entry.surfaceObject); // Note entry.worldAnchorChild is child of surfaceObject, so will get destroyed // along with components. } break; } }
private void FixedUpdate() { if (!PhotonNetwork.InRoom) { return; } if (PMT == null) { PMT = PhotonMeshTransfer.getSingleton(); } //DONT PISS OFF PHOTON BY SENDING TOO FREQUENTLY! THEY WILL KICK YOU! if (lastMeshDownlinkTime + deltaTimeAveraged + deltaTimeAveraged * 0.001f * lastMeshSize * (ConnectAndJoinSpaace.disconnectCount + 1) < Time.realtimeSinceStartup) { SurfacesList.Sort(); // you can't block here and wait for the camera capture. // Send the old data and trigger a new capture. // NetworkMeshSource.getSingleton() for (int index = 0; index < SurfacesList.Count; index++) { SurfaceEntry item = SurfacesList[index]; if (item.m_BakedState == BakedState.Baked || item.m_BakedState == BakedState.UpdatePostBake) { //Debug.LogWarning("Mesh " + item.m_Id + " has baked state " + item.m_BakedState); GameObject go = item.m_Surface; if (go) { MeshFilter[] meshFilters = go.GetComponents <MeshFilter>(); for (int mfi = 0; mfi < meshFilters.Length; mfi++) { MeshFilter MFer = meshFilters[mfi]; if (MFer) { //Debug.LogWarning("Mesh " + item.m_Id + " has a mesh filter"); Mesh meesh = MFer.mesh; if (meesh && meesh.triangles.Length > 0) { //Debug.LogWarning("Mesh " + item.m_Id +" is of length "+ meesh.triangles.Length); if (Time.realtimeSinceStartup - item.lastSentTime > 30.0f) { if (PMT == null) { Debug.LogWarning("PMT IS NULL! Can't send mesh " + item.m_Id); } //just send one and return; item.lastSentTime = lastMeshDownlinkTime = Time.realtimeSinceStartup; PMT.sendMesh(go.transform.position, go.transform.rotation, meesh); lastMeshSize = meesh.triangles.Length; //add any meshes we send to the minimap MiniMapHandler.getSingleton().addElement(meesh, go.transform.position, go.transform.rotation); //Debug.LogWarning("Mesh transer initiated on index " + item.m_Id); return; } } } } } } } lastMeshDownlinkTime = Time.realtimeSinceStartup; } }
// This makes new vertices as well as floor and ceiling surfaces internal void CreateSurfaces() { if (updateneeded) { // Brightness color int brightint = General.Map.Renderer2D.CalculateBrightness(brightness); // villsa switch (General.Map.Renderer2D.ViewMode) { case ViewMode.FloorColor: brightint = this.flrColor.color.ToInt(); break; case ViewMode.CeilingColor: brightint = this.ceilColor.color.ToInt(); break; case ViewMode.ThingColor: brightint = this.thingColor.color.ToInt(); break; default: break; } // Make vertices flatvertices = new FlatVertex[triangles.Vertices.Count]; for (int i = 0; i < triangles.Vertices.Count; i++) { flatvertices[i].x = triangles.Vertices[i].x; flatvertices[i].y = triangles.Vertices[i].y; flatvertices[i].z = 1.0f; flatvertices[i].c = brightint; flatvertices[i].u = triangles.Vertices[i].x; flatvertices[i].v = triangles.Vertices[i].y; } // Create bounding box bbox = CreateBBox(); // Make a dummy entry if we don't have one yet if (surfaceentry == null) { surfaceentry = new SurfaceEntry(-1, -1, -1); } // Create floor vertices FlatVertex[] floorvertices = new FlatVertex[flatvertices.Length]; flatvertices.CopyTo(floorvertices, 0); General.Plugins.OnSectorFloorSurfaceUpdate(this, ref floorvertices); surfaceentry.floorvertices = floorvertices; surfaceentry.floortexture = longfloortexname; // Create ceiling vertices FlatVertex[] ceilvertices = new FlatVertex[flatvertices.Length]; flatvertices.CopyTo(ceilvertices, 0); General.Plugins.OnSectorCeilingSurfaceUpdate(this, ref ceilvertices); surfaceentry.ceilvertices = ceilvertices; surfaceentry.ceiltexture = longceiltexname; // Update entry surfaceentry = General.Map.CRenderer2D.Surfaces.UpdateSurfaces(surfaceentry); // Updated updateneeded = false; } }
// Update is called once per frame void Update() { if (visibility == MeshVisible.DISABLED) { foreach (SurfaceEntry surfaceEntry in surfaces.Values) { surfaceEntry.gameObject.GetComponent <MeshRenderer>().enabled = false; } } if (ScanProgress.Instance.GetState() == ScanProgress.State.Finished) { return; } // request update from observer if (lastUpdateTime + updateFrequencyInSeconds < Time.realtimeSinceStartup) { lastUpdateTime = Time.realtimeSinceStartup; observer.Update(onSurfaceChanged); } // update priorities to bake the mesh the user is looking at Ray gazeRay = new Ray(Camera.main.transform.position, Camera.main.transform.forward); foreach (SurfaceEntry entry in bakingQueue) { if (entry.aabb.IntersectRay(gazeRay)) { entry.lastLookedAtTime = Time.realtimeSinceStartup; } } // bake the mesh if (!isBaking && bakingQueue.Count > 0) { SurfaceEntry surfaceEntry = bakingQueue.Pop(); SurfaceData request = new SurfaceData(); request.id.handle = surfaceEntry.id; request.outputMesh = surfaceEntry.gameObject.GetComponent <MeshFilter>(); request.outputAnchor = surfaceEntry.gameObject.GetComponent <WorldAnchor>(); request.trianglesPerCubicMeter = 300.0f; try { if (observer.RequestMeshAsync(request, onSurfaceDataReady)) { isBaking = true; } else { Debug.Log(System.String.Format("Bake request for {0} failed. Is {0} a valid Surface ID?", surfaceEntry.id)); } } catch { Debug.Log(System.String.Format("Bake for id {0} failed unexpectedly!", surfaceEntry.id)); } } // Update mesh colors foreach (SurfaceEntry surfaceEntry in surfaces.Values) { MeshRenderer meshRenderer = surfaceEntry.gameObject.GetComponent <MeshRenderer>(); Color currentColor = Color.Lerp(startColor, endColor, (Time.realtimeSinceStartup - surfaceEntry.lastUpdateTime) / cooldownPeriod); meshRenderer.sharedMaterial.SetColor("_WireColor", currentColor); } }