Ejemplo n.º 1
0
 // Functions
 private void Awake()
 {
     // Cache references to required component
     UnderstandingDLL        = new SpatialUnderstandingDll();
     UnderstandingSourceMesh = GetComponent <SpatialUnderstandingSourceMesh>();
     UnderstandingCustomMesh = GetComponent <SpatialUnderstandingCustomMesh>();
 }
Ejemplo n.º 2
0
 // 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);
        }
Ejemplo n.º 4
0
        /// <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;
        }