示例#1
0
    private void Update()
    {
        HoloToolkit.Unity.SpatialMapping.OrientedBoundingBox obb = OBBMeshIntersection.CreateWorldSpaceOBB(GetComponent <BoxCollider>());
        List <int> intersecting = OBBMeshIntersection.FindTriangles(obb, m_triangleMesh.vertices, m_triangleMesh.GetTriangles(0), m_triangleXform);

        GetComponent <Renderer>().material.color = intersecting.Count > 0 ? Color.red : Color.green;
    }
    void Start()
    {
        BoxCollider obb  = obbParent.GetComponent <BoxCollider>();
        Mesh        mesh = meshParent.GetComponent <MeshFilter>().sharedMesh;

        Debug.Log("OBB-Mesh Intersection Result: " + (OBBMeshIntersection.FindTriangles(obb, mesh.vertices, mesh.GetTriangles(0), meshParent.transform).Count > 0));
    }
示例#3
0
    private void CreateBulletHole(Vector3 position, Vector3 normal)
    {
        GameObject bulletHole = Instantiate(m_bulletHolePrefab, position, Quaternion.LookRotation(normal)) as GameObject;

        bulletHole.transform.parent = this.transform;
        OrientedBoundingBox obb = OBBMeshIntersection.CreateWorldSpaceOBB(bulletHole.GetComponent <BoxCollider>());

        SurfacePlaneDeformationManager.Instance.Embed(bulletHole, obb, position, () => { Debug.Log("Embed complete"); }, true);
    }
    private void CreateBulletHole(Vector3 position, Vector3 normal, SurfacePlane plane)
    {
        GameObject bulletHole = Instantiate(m_bulletHolePrefab, position, Quaternion.LookRotation(normal)) as GameObject;

        bulletHole.AddComponent <WorldAnchor>(); // does this do anything?
        bulletHole.transform.parent = this.transform;
        OrientedBoundingBox obb = OBBMeshIntersection.CreateWorldSpaceOBB(bulletHole.GetComponent <BoxCollider>());

        SurfacePlaneDeformationManager.Instance.Embed(bulletHole, obb, plane);
    }
示例#5
0
    // SpatialUnderstanding case
    public void CreateBulletHole(Vector3 position, Vector3 normal)
    {
        GameObject bulletHole = Instantiate(bulletHolePrefab, position + normal * .005f, Quaternion.LookRotation(normal)) as GameObject;

        bulletHole.transform.parent = this.transform;
        SurfacePlaneDeformationManager.Instance.Embed(bulletHole, OBBMeshIntersection.CreateWorldSpaceOBB(bulletHole.GetComponent <BoxCollider>()), bulletHole.transform.position);
        //TODO: logic for objects to self destruct after not being gazed at for long enough?
        m_bulletHoles.Enqueue(bulletHole);
        while (m_bulletHoles.Count > maxBulletHoles)
        {
            GameObject oldBulletHole = m_bulletHoles.Dequeue();
            if (oldBulletHole) // if hasn't destroyed itself already
            {
                Destroy(oldBulletHole);
            }
        }
    }
示例#6
0
    private IEnumerator DeformSurfaceCoroutine()
    {
        while (m_requestQueue.Count > 0)
        {
            // Dequeue
            EmbedRequest request               = m_requestQueue.Dequeue();
            GameObject   marginVolume          = request.marginVolume;
            Vector3      marginFrontPlanePoint = request.centerPointOnFrontPlane;
            Vector3      marginBackPlanePoint  = request.centerPointOnBackPlane;
            GameObject   embedded              = request.embedded;

            // Get the OBB that describes the margin volume we want to create
            BoxCollider obb = marginVolume.GetComponent <BoxCollider>();

            /*
             * Compute a back-plane located directly behind the embedded object.
             * Triangles that intersect with the embedded object's OBB will be
             * projected onto this back plane. The projection formula is:
             *
             *  v' = v - n * (Dot(n, v) + planeToOriginDistance)
             *
             * Where n is the normal pointing toward the spatial mesh and
             * planeToOriginDistance is solved for using the plane equation.
             *
             * We assume the OBB's position is located at the front-facing side of the
             * embedded object rather than in its center.
             */
            Vector3 intoSurface           = marginBackPlanePoint - marginFrontPlanePoint;
            Vector3 intoSurfaceNormal     = Vector3.Normalize(intoSurface);
            float   planeToOriginDistance = 0 - Vector3.Dot(intoSurfaceNormal, marginBackPlanePoint); // Ax+By+Cz+D=0, solving for D here

            // The thickness of the embedded object can easily be obtained from the
            // desired distance between the margin volume's front and back planes
            float requiredMargin = Vector3.Magnitude(intoSurface);

            // Check against each spatial mesh and deform those that intersect the
            // margin volume
            foreach (MeshFilter meshFilter in m_spatialMeshFilters)
            {
                if (meshFilter == null)
                {
                    continue;
                }

                if (request.HasSufficientMargin(meshFilter, requiredMargin))
                {
                    //Debug.Log("Skipping [" + task.plane.GetInstanceID() + "," + meshFilter.GetInstanceID() + "] due to sufficient margin");
                    continue;
                }

                // Detect all triangles that intersect with the margin volume OBB
                Mesh mesh = meshFilter.sharedMesh;
                if (mesh == null)
                {
                    continue;
                }
                Vector3[]   verts   = mesh.vertices; // spatial mesh has vertices and normals, no UVs
                Vector3[]   normals = mesh.normals;
                List <int>  intersectingTriangles = null;
                IEnumerator f = OBBMeshIntersection.FindTrianglesCoroutine((List <int> result) => { intersectingTriangles = result; }, maxSecondsPerFrame, obb, verts, mesh.GetTriangles(0), meshFilter.transform);
                while (f.MoveNext())
                {
                    yield return(f.Current);
                }
                if (intersectingTriangles.Count == 0)
                {
                    //Debug.Log("No intersecting triangles found in: " + meshFilter.gameObject.name);
                    continue;
                }

                // TODO: Use a bit set to keep track of which vertex indices to modify?

                float      t0          = Time.realtimeSinceStartup;
                List <int> vertIndices = intersectingTriangles;

                // Modify spatial mesh by pushing vertices inward onto the back plane of
                // the margin volume
                foreach (int i in vertIndices)
                {
                    Vector3 worldVert    = meshFilter.transform.TransformPoint(verts[i]);
                    float   displacement = Vector3.Dot(intoSurfaceNormal, worldVert) + planeToOriginDistance;
                    worldVert = worldVert - displacement * intoSurfaceNormal;
                    verts[i]  = meshFilter.transform.InverseTransformPoint(worldVert);
                    if (Time.realtimeSinceStartup - t0 >= maxSecondsPerFrame)
                    {
                        yield return(null);

                        t0 = Time.realtimeSinceStartup;
                    }
                }
                mesh.vertices = verts;    // apply changes
                mesh.RecalculateBounds(); // not needed because deformation should be minor
                if (Time.realtimeSinceStartup - t0 >= maxSecondsPerFrame)
                {
                    yield return(null);

                    t0 = Time.realtimeSinceStartup;
                }

                // Update margin depth of this plane/spatial mesh pair
                request.RecordMargin(meshFilter, requiredMargin);
                //Debug.Log("Finished deforming [" + task.plane.GetInstanceID() + "," + meshFilter.GetInstanceID() + "]");
            }

            // Restore embedded object's shared materials (and its render order) now
            // that margin exists in the spatial mesh. Clean up temporary objects.
            // Destroy temporary object
            embedded.GetComponent <SharedMaterialHelper>().RestoreSharedMaterials();
            Object.Destroy(marginVolume.GetComponent <BoxCollider>());
            Object.Destroy(marginVolume);
        }

        m_working = false;
        yield break;
    }
    private IEnumerator WorkRoutine()
    {
        while (m_work_queue.Count > 0)
        {
            // Dequeue and begin processing
            WorkUnit    work = m_work_queue.Dequeue();
            BoxCollider obb  = work.renderer.gameObject.GetComponent <BoxCollider>();
            if (obb == null)
            {
                Debug.Log("ERROR: Object " + work.renderer.gameObject.name + " lacks a box collider");
                m_working = false;
                yield break;
            }

            // Compute parameters for a projection plane behind embedded object
            Vector3 displacement_normal;
            float   plane_to_origin_distance;
            ComputeBackPlaneParameters(out displacement_normal, out plane_to_origin_distance, obb);

            // Check against each spatial mesh and deform those that intersect
            int num = 0;
            foreach (MeshFilter mesh_filter in m_spatialMeshFilters)
            {
                Debug.Log("Iterating... " + (num++));
                if (mesh_filter == null)
                {
                    continue;
                }

                //TODO: prefetch vertices/normals/uvs and indices because OBBMeshIntersection gets them, too, which is slow

                /*
                 * Step 3: Detect all triangles that intersect with our object
                 */
                Mesh mesh = mesh_filter.sharedMesh;
                if (mesh == null)
                {
                    continue;
                }
                List <int> intersecting_triangles = new List <int>();
                Vector3[]  verts   = mesh.vertices; // spatial mesh has vertices and normals, no UVs
                Vector3[]  normals = mesh.normals;
                OBBMeshIntersection.ResultsCallback results = delegate(List <int> intersecting_triangles_found) { intersecting_triangles = intersecting_triangles_found; };
                IEnumerator f = OBBMeshIntersection.FindTrianglesCoroutine(results, maxSecondsPerFrame, obb, verts, mesh.GetTriangles(0), mesh_filter.transform);
                while (f.MoveNext())
                {
                    yield return(f.Current);
                }
                if (intersecting_triangles.Count == 0)
                {
                    continue;
                }
                float      t0           = Time.realtimeSinceStartup;
                List <int> vert_indices = MakeSetOfVertexIndices(intersecting_triangles);

                /*
                 * Step 4: Create a new set of vertices and triangles out of the affected
                 * ones to save their state before we alter them in the original mesh.
                 * This "patch" mesh will be drawn after spatial meshes and embedded
                 * objects.
                 *
                 * Step 5: Save the game object along with a mapping of the modified
                 * vertices so we can undo changes later.
                 *
                 * Step 6: Create a new GameObject to hold a mesh with the saved
                 * vertices. Note that the vertices were in spatial mesh local
                 * coordinates, so we copy the spatial mesh transform to position them
                 * correctly in world space.
                 *
                 * Step 7: Reassign render order of saved triangles to a lower priority
                 * than embedded object, so that they are rendered after
                 */
                CreatePatchObject(mesh, mesh_filter, intersecting_triangles, verts, normals, vert_indices);
                if (Time.realtimeSinceStartup - t0 >= maxSecondsPerFrame)
                {
                    yield return(null);

                    t0 = Time.realtimeSinceStartup;
                }

                /*
                 * Step 8: Modify the spatial mesh's vertices by pushing them inward
                 * along axis of normal
                 */
                foreach (int i in vert_indices)
                {
                    Vector3 world_vert   = mesh_filter.transform.TransformPoint(verts[i]);
                    float   displacement = Vector3.Dot(displacement_normal, world_vert) + plane_to_origin_distance;
                    world_vert = world_vert - displacement * displacement_normal;
                    verts[i]   = mesh_filter.transform.InverseTransformPoint(world_vert);
                }
                mesh.vertices = verts; // apply changes
                mesh.RecalculateBounds();
                if (Time.realtimeSinceStartup - t0 >= maxSecondsPerFrame)
                {
                    yield return(null);

                    t0 = Time.realtimeSinceStartup;
                }
                if (updateCollider)
                {
                    MeshCollider collider = mesh_filter.gameObject.GetComponent <MeshCollider>();
                    if (collider != null)
                    {
                        collider.sharedMesh = null;
                        collider.sharedMesh = mesh;
                    }
                    if (Time.realtimeSinceStartup - t0 >= maxSecondsPerFrame)
                    {
                        yield return(null);

                        t0 = Time.realtimeSinceStartup;
                    }
                }
            }

            /*
             * Step 9: Reassign render order of embedded object to be just after the
             * spatial mesh layer but before patches. We
             */
            SharedMaterialHelper helper = work.renderer.gameObject.GetComponent <SharedMaterialHelper>();
            if (helper != null)
            {
                // Apply clones of the shared material. Only a single clone is ever
                // instantiated, which is much more efficient than Unity's default
                // behavior of cloning materials[] for each object!
                helper.ApplySharedMaterialClones();
            }
            foreach (Material material in work.renderer.materials)
            {
                material.renderQueue = material.renderQueue + (spatialMeshRenderQueueValue - highPriorityRenderQueueValue) + 1;
            }
        }

        m_working = false;
    }