// Functions private void Awake() { // Cache references to required component UnderstandingDLL = new SpatialUnderstandingDll(); UnderstandingSourceMesh = GetComponent <SpatialUnderstandingSourceMesh>(); UnderstandingCustomMesh = GetComponent <SpatialUnderstandingCustomMesh>(); }
// Functions protected override void Awake() { base.Awake(); // Cache references to required component UnderstandingDLL = new SpatialUnderstandingDll(); UnderstandingSourceMesh = GetComponent <SpatialUnderstandingSourceMesh>(); UnderstandingCustomMesh = GetComponent <SpatialUnderstandingCustomMesh>(); }
/// <summary> /// Update the internal mesh list and provides an array pointer in /// the form the dll will accept. /// </summary> /// <param name="meshCount">Number of meshes contains in the return mesh list</param> /// <param name="meshList">Marshalled mesh list pointer. Valid only with the caller's function context</param> /// <returns></returns> public bool GetInputMeshList(out int meshCount, out IntPtr meshList) { if (inputMeshList.Count == 0) { meshCount = 0; meshList = IntPtr.Zero; return(false); } // Convert to IntPtr SpatialUnderstandingDll dll = SpatialUnderstanding.Instance.UnderstandingDLL; meshCount = inputMeshList.Count; meshList = dll.PinMeshDataForMarshalling(inputMeshList); return(true); }
/// <summary> /// Imports the custom mesh from the dll. This a a coroutine which will take multiple frames to complete. /// </summary> /// <returns></returns> public IEnumerator Import_UnderstandingMesh() { var stopwatch = System.Diagnostics.Stopwatch.StartNew(); int startFrameCount = Time.frameCount; if (!spatialUnderstanding.AllowSpatialUnderstanding || IsImportActive) { yield break; } IsImportActive = true; SpatialUnderstandingDll dll = spatialUnderstanding.UnderstandingDLL; Vector3[] meshVertices = null; Vector3[] meshNormals = null; Int32[] meshIndices = null; // Pull the mesh - first get the size, then allocate and pull the data int vertCount; int idxCount; if ((SpatialUnderstandingDll.Imports.GeneratePlayspace_ExtractMesh_Setup(out vertCount, out idxCount) > 0) && (vertCount > 0) && (idxCount > 0)) { meshVertices = new Vector3[vertCount]; IntPtr vertPos = dll.PinObject(meshVertices); meshNormals = new Vector3[vertCount]; IntPtr vertNorm = dll.PinObject(meshNormals); meshIndices = new Int32[idxCount]; IntPtr indices = dll.PinObject(meshIndices); SpatialUnderstandingDll.Imports.GeneratePlayspace_ExtractMesh_Extract(vertCount, vertPos, vertNorm, idxCount, indices); } // Wait a frame stopwatch.Stop(); yield return(null); stopwatch.Start(); // Create output meshes if ((meshVertices != null) && (meshVertices.Length > 0) && (meshIndices != null) && (meshIndices.Length > 0)) { // first get all our mesh data containers ready for meshes. foreach (MeshData meshdata in meshSectors.Values) { meshdata.Reset(); } float startTime = Time.realtimeSinceStartup; // first we need to split the playspace up into segments so we don't always // draw everything. We can break things up in to cubic meters. for (int index = 0; index < meshIndices.Length; index += 3) { Vector3 firstVertex = meshVertices[meshIndices[index]]; Vector3 secondVertex = meshVertices[meshIndices[index + 1]]; Vector3 thirdVertex = meshVertices[meshIndices[index + 2]]; // The triangle may belong to multiple sectors. We will copy the whole triangle // to all of the sectors it belongs to. This will fill in seams on sector edges // although it could cause some amount of visible z-fighting if rendering a wireframe. Vector3 firstSector = VectorToSector(firstVertex); AddTriangleToSector(firstSector, firstVertex, secondVertex, thirdVertex); // If the second sector doesn't match the first, copy the triangle to the second sector. Vector3 secondSector = VectorToSector(secondVertex); if (secondSector != firstSector) { AddTriangleToSector(secondSector, firstVertex, secondVertex, thirdVertex); } // If the third sector matches neither the first nor second sector, copy the triangle to the // third sector. Vector3 thirdSector = VectorToSector(thirdVertex); if (thirdSector != firstSector && thirdSector != secondSector) { AddTriangleToSector(thirdSector, firstVertex, secondVertex, thirdVertex); } // Limit our run time so that we don't cause too many frame drops. // Only checking every few iterations or so to prevent losing too much time to checking the clock. if ((index % 30 == 0) && ((Time.realtimeSinceStartup - startTime) > MaxFrameTimeInSeconds)) { // Debug.LogFormat("{0} of {1} processed", index, meshIndices.Length); stopwatch.Stop(); yield return(null); stopwatch.Start(); startTime = Time.realtimeSinceStartup; } } startTime = Time.realtimeSinceStartup; // Now we have all of our triangles assigned to the correct mesh, we can make all of the meshes. // Each sector will have its own mesh. foreach (MeshData meshData in meshSectors.Values) { // Construct the mesh. meshData.Commit(); // Make sure we don't build too many meshes in a single frame. if ((Time.realtimeSinceStartup - startTime) > MaxFrameTimeInSeconds) { stopwatch.Stop(); yield return(null); stopwatch.Start(); startTime = Time.realtimeSinceStartup; } } } // Wait a frame stopwatch.Stop(); yield return(null); stopwatch.Start(); // All done - can free up marshal pinned memory dll.UnpinAllObjects(); // Done IsImportActive = false; // Mark the timestamp timeLastImportedMesh = Time.time; stopwatch.Stop(); int deltaFrameCount = (Time.frameCount - startFrameCount + 1); if (stopwatch.Elapsed.TotalSeconds > 0.75) { Debug.LogWarningFormat("Import_UnderstandingMesh took {0:N0} frames ({1:N3} ms)", deltaFrameCount, stopwatch.Elapsed.TotalMilliseconds ); } }
// Functions /// <summary> /// Imports the custom mesh from the dll. This a a coroutine which will take multiple frames to complete. /// </summary> /// <returns></returns> #if UNITY_EDITOR || UNITY_WSA public IEnumerator Import_UnderstandingMesh() { if (!SpatialUnderstanding.Instance.AllowSpatialUnderstanding) { yield break; } SpatialUnderstandingDll dll = SpatialUnderstanding.Instance.UnderstandingDLL; Vector3[] meshVertices = null; Vector3[] meshNormals = null; Int32[] meshIndices = null; try { // Pull the mesh - first get the size, then allocate and pull the data int vertCount, idxCount; if ((SpatialUnderstandingDll.Imports.GeneratePlayspace_ExtractMesh_Setup(out vertCount, out idxCount) > 0) && (vertCount > 0) && (idxCount > 0)) { meshVertices = new Vector3[vertCount]; IntPtr vertPos = dll.PinObject(meshVertices); meshNormals = new Vector3[vertCount]; IntPtr vertNorm = dll.PinObject(meshNormals); meshIndices = new Int32[idxCount]; IntPtr indices = dll.PinObject(meshIndices); SpatialUnderstandingDll.Imports.GeneratePlayspace_ExtractMesh_Extract(vertCount, vertPos, vertNorm, idxCount, indices); } } catch (Exception ex) { Debug.LogError(ex.ToString()); } // Wait a frame yield return(null); try { // Clear Cleanup(); // Create output mesh if ((meshVertices != null) && (meshVertices.Length > 0) && (meshIndices != null) && (meshIndices.Length > 0)) { if (customMesh != null) { Destroy(customMesh); } customMesh = new Mesh { vertices = meshVertices, normals = meshNormals, triangles = meshIndices }; GameObject spatialMesh = AddSurfaceObject(customMesh, string.Format("SurfaceUnderstanding Mesh-{0}", transform.childCount), transform); spatialMesh.AddComponent <UnityEngine.VR.WSA.WorldAnchor>(); } } catch (Exception ex) { Debug.LogError(ex.ToString()); } // Wait a frame yield return(null); // All done - can free up marshal pinned memory dll.UnpinAllObjects(); // Done isImportActive = false; }
/// <summary> /// Imports the custom mesh from the dll. This a a coroutine which will take multiple frames to complete. /// </summary> /// <returns></returns> public IEnumerator Import_UnderstandingMesh() { if (!spatialUnderstanding.AllowSpatialUnderstanding || IsImportActive) { yield break; } IsImportActive = true; SpatialUnderstandingDll dll = spatialUnderstanding.UnderstandingDLL; Vector3[] meshVertices = null; Vector3[] meshNormals = null; Int32[] meshIndices = null; // Pull the mesh - first get the size, then allocate and pull the data int vertCount; int idxCount; if ((SpatialUnderstandingDll.Imports.GeneratePlayspace_ExtractMesh_Setup(out vertCount, out idxCount) > 0) && (vertCount > 0) && (idxCount > 0)) { meshVertices = new Vector3[vertCount]; IntPtr vertPos = dll.PinObject(meshVertices); meshNormals = new Vector3[vertCount]; IntPtr vertNorm = dll.PinObject(meshNormals); meshIndices = new Int32[idxCount]; IntPtr indices = dll.PinObject(meshIndices); SpatialUnderstandingDll.Imports.GeneratePlayspace_ExtractMesh_Extract(vertCount, vertPos, vertNorm, idxCount, indices); } // Wait a frame yield return(null); // Create output meshes if ((meshVertices != null) && (meshVertices.Length > 0) && (meshIndices != null) && (meshIndices.Length > 0)) { // first get all our mesh data containers ready for meshes. foreach (MeshData meshdata in meshSectors.Values) { meshdata.Reset(); } DateTime startTime = DateTime.Now; // first we need to split the playspace up into segments so we don't always // draw everything. We can break things up in to cubic meters. for (int index = 0; index < meshIndices.Length; index += 3) { Vector3 firstVertex = meshVertices[meshIndices[index]]; Vector3 secondVertex = meshVertices[meshIndices[index + 1]]; Vector3 thirdVertex = meshVertices[meshIndices[index + 2]]; // The triangle may belong to multiple sectors. We will copy the whole triangle // to all of the sectors it belongs to. This will fill in seams on sector edges // although it could cause some amount of visible z-fighting if rendering a wireframe. Vector3 firstSector = VectorToSector(firstVertex); AddTriangleToSector(firstSector, firstVertex, secondVertex, thirdVertex); // If the second sector doesn't match the first, copy the triangle to the second sector. Vector3 secondSector = VectorToSector(secondVertex); if (secondSector != firstSector) { AddTriangleToSector(secondSector, firstVertex, secondVertex, thirdVertex); } // If the third sector matches neither the first nor second sector, copy the triangle to the // third sector. Vector3 thirdSector = VectorToSector(thirdVertex); if (thirdSector != firstSector && thirdSector != secondSector) { AddTriangleToSector(thirdSector, firstVertex, secondVertex, thirdVertex); } // Limit our run time so that we don't cause too many frame drops. // Only checking every 10 iterations or so to prevent losing too much time to checking the clock. if (index % 30 == 0 && (DateTime.Now - startTime).TotalMilliseconds > MaxFrameTime) { // Debug.LogFormat("{0} of {1} processed", index, meshIndices.Length); yield return(null); startTime = DateTime.Now; } } startTime = DateTime.Now; // Now we have all of our triangles assigned to the correct mesh, we can make all of the meshes. // Each sector will have its own mesh. for (int meshSectorsIndex = 0; meshSectorsIndex < meshSectors.Values.Count; meshSectorsIndex++) { // Make a object to contain the mesh, mesh renderer, etc or reuse one from before. // It shouldn't matter if we switch which one of these has which mesh from call to call. // (Actually there is potential that a sector won't render for a few frames, but this should // be rare). if (SurfaceObjects.Count <= meshSectorsIndex) { AddSurfaceObject(null, string.Format("SurfaceUnderstanding Mesh-{0}", meshSectorsIndex), transform); } // Get the next MeshData. MeshData meshData = meshSectors.Values.ElementAt(meshSectorsIndex); // Construct the mesh. meshData.Commit(); // Assign the mesh to the surface object. SurfaceObjects[meshSectorsIndex].Filter.sharedMesh = meshData.MeshObject; // Make sure we don't build too many meshes in a single frame. if ((DateTime.Now - startTime).TotalMilliseconds > MaxFrameTime) { yield return(null); startTime = DateTime.Now; } } // The current flow of the code shouldn't allow for there to be more Surfaces than sectors. // In the future someone might want to destroy meshSectors where there is no longer any // geometry. if (SurfaceObjects.Count > meshSectors.Values.Count) { Debug.Log("More surfaces than mesh sectors. This is unexpected"); } } // Wait a frame yield return(null); // All done - can free up marshal pinned memory dll.UnpinAllObjects(); // Done IsImportActive = false; // Mark the timestamp timeLastImportedMesh = DateTime.Now; }
/// <summary> /// Imports the custom mesh from the dll. This a a coroutine which will take multiple frames to complete. /// </summary> /// <returns></returns> public IEnumerator Import_UnderstandingMesh() { if (!spatialUnderstanding.AllowSpatialUnderstanding || IsImportActive) { yield break; } IsImportActive = true; SpatialUnderstandingDll dll = spatialUnderstanding.UnderstandingDLL; Vector3[] meshVertices = null; Vector3[] meshNormals = null; Int32[] meshIndices = null; // Pull the mesh - first get the size, then allocate and pull the data int vertCount; int idxCount; if ((SpatialUnderstandingDll.Imports.GeneratePlayspace_ExtractMesh_Setup(out vertCount, out idxCount) > 0) && (vertCount > 0) && (idxCount > 0)) { meshVertices = new Vector3[vertCount]; IntPtr vertPos = dll.PinObject(meshVertices); meshNormals = new Vector3[vertCount]; IntPtr vertNorm = dll.PinObject(meshNormals); meshIndices = new Int32[idxCount]; IntPtr indices = dll.PinObject(meshIndices); SpatialUnderstandingDll.Imports.GeneratePlayspace_ExtractMesh_Extract(vertCount, vertPos, vertNorm, idxCount, indices); } // Wait a frame yield return(null); // Create output meshes if ((meshVertices != null) && (meshVertices.Length > 0) && (meshIndices != null) && (meshIndices.Length > 0)) { // first get all our mesh data containers ready for meshes. foreach (MeshData meshdata in meshSectors.Values) { meshdata.Reset(); } DateTime startTime = DateTime.Now; // first we need to split the playspace up into segments so we don't always // draw everything. We can break things up in to cubic meters. for (int index = 0; index < meshIndices.Length; index += 3) { Vector3 firstVertex = meshVertices[meshIndices[index]]; Vector3 secondVertex = meshVertices[meshIndices[index + 1]]; Vector3 thirdVertex = meshVertices[meshIndices[index + 2]]; // Use the first vertex to decide which sector to put the triangle into. // Ultimately all of the triangles end up in a mesh, so the resulting render should // be identical. Vector3 triangleSector = VectorToSector(firstVertex); // Grab the mesh container we are using for this sector. MeshData nextSectorData; if (!meshSectors.TryGetValue(triangleSector, out nextSectorData)) { // Or make it if this is a new sector. nextSectorData = new MeshData(); meshSectors.Add(triangleSector, nextSectorData); } // Add the vertices to the sector's mesh container. nextSectorData.AddTriangle(firstVertex, secondVertex, thirdVertex); // Limit our run time so that we don't cause too many frame drops. // Only checking every 10 iterations or so to prevent losing too much time to checking the clock. if (index % 30 == 0 && (DateTime.Now - startTime).TotalMilliseconds > MaxFrameTime) { // Debug.LogFormat("{0} of {1} processed", index, meshIndices.Length); yield return(null); startTime = DateTime.Now; } } yield return(null); // Clear our old surface objects. Cleanup(); yield return(null); startTime = DateTime.Now; // now we have all of our triangles assigned to the correct mesh, we can make all of the meshes. foreach (MeshData meshdata in meshSectors.Values) { // Tell the meshdata class to generate its mesh. meshdata.Commit(); // And create a surface object using the mesh. AddSurfaceObject(meshdata.MeshObject, string.Format("SurfaceUnderstanding Mesh-{0}", transform.childCount), transform).AddComponent <WorldAnchor>(); // Limit our run time so that we don't cause too many frame drops. if ((DateTime.Now - startTime).TotalMilliseconds > MaxFrameTime) { yield return(null); startTime = DateTime.Now; } } } // Wait a frame yield return(null); // All done - can free up marshal pinned memory dll.UnpinAllObjects(); // Done IsImportActive = false; // Mark the timestamp timeLastImportedMesh = DateTime.Now; }