Exemple #1
0
        /// <summary>
        /// Adds new bounding objects to the end of the Queue.
        /// </summary>
        /// <param name="boundingObjects">Collection of GameObjects which define the bounds where spatial mesh vertices should be removed.</param>
        private void AddBoundingObjectsToQueue(IEnumerable <GameObject> boundingObjects, bool createMesh)
        {
            foreach (GameObject item in boundingObjects)
            {
                Bounds bounds = new Bounds();

                Collider boundingCollider = item.GetComponent <Collider>();
                if (boundingCollider != null)
                {
                    bounds = boundingCollider.bounds;

                    // Expand the bounds, if requested.
                    if (BoundsExpansion > 0.0f)
                    {
                        bounds.Expand(BoundsExpansion);
                    }

                    BoundsContainer container = new BoundsContainer();
                    container.bounds     = bounds;
                    container.createMesh = createMesh;
                    boundingObjectsQueue.Enqueue(container);
                }
            }
        }
Exemple #2
0
        /// <summary>
        /// Iterator block, analyzes surface meshes to find vertices existing within the bounds of any boundingObject and removes them.
        /// </summary>
        /// <returns>Yield result.</returns>
        private IEnumerator RemoveSurfaceVerticesWithinBoundsRoutine()
        {
            List <MeshFilter> meshFilters = SpatialMappingManager.Instance.GetMeshFilters();
            float             start       = Time.realtimeSinceStartup;

            List <Vector3> removedObjectVertices = new List <Vector3>();
            List <Vector3> removedObjectNormals  = new List <Vector3>();
            List <int>     removedObjectIndices  = new List <int>();

            while (boundingObjectsQueue.Count > 0)
            {
                // Get the current boundingObject.
                BoundsContainer container = boundingObjectsQueue.Dequeue();
                Bounds          bounds    = container.bounds;

                foreach (MeshFilter filter in meshFilters)
                {
                    // Since this is amortized across frames, the filter can be destroyed by the time
                    // we get here.
                    if (filter == null)
                    {
                        continue;
                    }

                    Mesh         mesh     = filter.sharedMesh;
                    MeshRenderer renderer = filter.GetComponent <MeshRenderer>();

                    // The mesh renderer bounds are in world space.
                    // If the mesh is null there is nothing to process
                    // If the renderer is null we can't get the renderer bounds
                    // If the renderer's bounds aren't contained inside of the current
                    // bounds from the bounds queue there is no reason to process
                    // If any of the above conditions are met, then we should go to the next meshfilter.
                    if (mesh == null || renderer == null || !renderer.bounds.Intersects(bounds))
                    {
                        continue;
                    }

                    // Remove vertices from any mesh that intersects with the bounds.
                    Vector3[]  verts         = mesh.vertices;
                    List <int> vertsToRemove = new List <int>();

                    // Find which mesh vertices are within the bounds.
                    for (int i = 0; i < verts.Length; ++i)
                    {
                        if (bounds.Contains(filter.transform.TransformPoint(verts[i])))
                        {
                            // These vertices are within bounds, so mark them for removal.
                            vertsToRemove.Add(i);
                        }

                        // If too much time has passed, we need to return control to the main game loop.
                        if ((Time.realtimeSinceStartup - start) > FrameTime)
                        {
                            // Pause our work here, and continue finding vertices to remove on the next frame.
                            yield return(null);

                            start = Time.realtimeSinceStartup;
                        }
                    }

                    // If we did not find any vertices to remove, continue to the next mesh.
                    if (vertsToRemove.Count == 0)
                    {
                        continue;
                    }

                    // We found vertices to remove, so now we need to remove any triangles that reference these vertices.
                    int[]      indices          = mesh.GetTriangles(0);
                    List <int> updatedIndices   = new List <int>();
                    List <int> removedIndices   = new List <int>();
                    List <int> boundaryVertices = new List <int>();

                    for (int index = 0; index < indices.Length; index += 3)
                    {
                        // Each triangle utilizes three slots in the index buffer, check to see if any of the
                        // triangle indices contain a vertex that should be removed.
                        int  indexA    = indices[index];
                        int  indexB    = indices[index + 1];
                        int  indexC    = indices[index + 2];
                        bool containsA = vertsToRemove.Contains(indexA);
                        bool containsB = vertsToRemove.Contains(indexB);
                        bool containsC = vertsToRemove.Contains(indexC);
                        if (containsA || containsB || containsC)
                        {
                            // Do nothing, we don't want to save this triangle...
                            // Instead, keep track of it for the removed mesh
                            removedIndices.Add(indexA);
                            removedIndices.Add(indexB);
                            removedIndices.Add(indexC);
                            // Also add any vertices that will be needed to reproduce the triangles in the removed mesh
                            if (!containsA && !boundaryVertices.Contains(indexA))
                            {
                                boundaryVertices.Add(indexA);
                            }
                            if (!containsB && !boundaryVertices.Contains(indexB))
                            {
                                boundaryVertices.Add(indexB);
                            }
                            if (!containsC && !boundaryVertices.Contains(indexC))
                            {
                                boundaryVertices.Add(indexC);
                            }
                        }
                        else
                        {
                            // Every vertex in this triangle is good, so let's save it.
                            updatedIndices.Add(indexA);
                            updatedIndices.Add(indexB);
                            updatedIndices.Add(indexC);
                        }

                        // If too much time has passed, we need to return control to the main game loop.
                        if ((Time.realtimeSinceStartup - start) > FrameTime)
                        {
                            // Pause our work, and continue making additional planes on the next frame.
                            yield return(null);

                            start = Time.realtimeSinceStartup;
                        }
                    }

                    // If none of the verts to remove were being referenced in the triangle list, continue
                    if (indices.Length == updatedIndices.Count)
                    {
                        continue;
                    }

                    // Update mesh to use the new triangles.
                    mesh.SetTriangles(updatedIndices.ToArray(), 0);
                    mesh.RecalculateBounds();
                    yield return(null);

                    start = Time.realtimeSinceStartup;

                    if (container.createMesh)
                    {
                        /* SETUP BUFFERS FOR REMOVED MESH */
                        SortedDictionary <int, int> vertexMap = new SortedDictionary <int, int>();
                        //List<int> remappedIndices = new List<int>();
                        vertsToRemove.AddRange(boundaryVertices);
                        vertsToRemove.Sort();
                        // Use a dictionary to allow faster remapping of indices
                        for (int k = 0; k < vertsToRemove.Count; k++)
                        {
                            int index = vertsToRemove[k];
                            vertexMap.Add(index, k + removedObjectVertices.Count);
                        }
                        // Add vertices to removed mesh
                        for (int k = 0; k < vertsToRemove.Count; k++)
                        {
                            int     index  = vertsToRemove[k];
                            Vector3 vertex = filter.transform.localToWorldMatrix.MultiplyPoint(verts[index]);
                            removedObjectVertices.Add(vertex);
                            Vector3 normal = mesh.normals[index];
                            removedObjectNormals.Add(normal);
                        }
                        // Add remapped indices to removed mesh
                        for (int k = 0; k < removedIndices.Count; k++)
                        {
                            int oldIndex = removedIndices[k];
                            int newIndex = vertexMap[oldIndex];
                            removedObjectIndices.Add(newIndex);
                        }

                        yield return(null);

                        start = Time.realtimeSinceStartup;
                    }

                    // Reset the mesh collider to fit the new mesh.
                    MeshCollider collider = filter.gameObject.GetComponent <MeshCollider>();
                    if (collider != null)
                    {
                        collider.sharedMesh = null;
                        collider.sharedMesh = mesh;
                    }
                }

                if (container.createMesh)
                {
                    // Create a GameObject from the removed vertices
                    createRemovedObject(removedObjectVertices, removedObjectNormals, removedObjectIndices);
                }
            }

            Debug.Log("Finished removing vertices.");

            // We are done removing vertices, trigger an event.
            EventHandler handler = RemoveVerticesComplete;

            if (handler != null)
            {
                handler(this, EventArgs.Empty);
            }

            removingVerts = false;
        }