Beispiel #1
0
        private static void AssertExpectedPlane(BoundedPlane plane, Vector3 bounds, Matrix4x4 vertDataTransform, Matrix4x4 meshTransform)
        {
            float expectedArea = 4.0f * bounds.x * bounds.y;
            Vector3 expectedPlaneNormal = meshTransform.TransformDirection(vertDataTransform.TransformDirection(new Vector3(0, 0, 1)));
            Vector3 expectedPlaneCenter = meshTransform.TransformPoint(vertDataTransform.TransformPoint(Vector3.zero));

            Assert.AreEqual(expectedArea, plane.Area, expectedArea * 0.01f);
            AssertAreEqual(expectedPlaneNormal, plane.Plane.normal, 0.01f, "Normal");
            AssertAreEqual(expectedPlaneCenter, plane.Bounds.Center, bounds.Length() * 0.01f, "Center");
        }
    private List <GameObject> GetTablesInDescendingAreaOrder()
    {
        List <GameObject> floors = m_playspace_manager.GetTables();

        floors.Sort((plane1, plane2) =>
        {
            HoloToolkit.Unity.BoundedPlane bp1 = plane1.GetComponent <HoloToolkit.Unity.SurfacePlane>().Plane;
            HoloToolkit.Unity.BoundedPlane bp2 = plane2.GetComponent <HoloToolkit.Unity.SurfacePlane>().Plane;
            // Sort descending
            return(bp2.Area.CompareTo(bp1.Area));
        });
        return(floors);
    }
Beispiel #3
0
        /// <summary>
        /// Marshals BoundedPlane data returned from a DLL API call into a managed BoundedPlane array
        /// and then frees the memory that was allocated within the DLL.
        /// </summary>
        /// <remarks>Disabling warning 618 when calling Marshal.SizeOf(), because
        /// Unity does not support .Net 4.5.1+ for using the preferred Marshal.SizeOf(T) method."/>, </remarks>
        private static BoundedPlane[] MarshalBoundedPlanesFromIntPtr(IntPtr outArray, int size)
        {
            BoundedPlane[] resArray = new BoundedPlane[size];
#pragma warning disable 618
            int structsize = Marshal.SizeOf(typeof(BoundedPlane));
#pragma warning restore 618
            IntPtr current = outArray;
            for (int i = 0; i < size; i++)
            {
#pragma warning disable 618
                resArray[i] = (BoundedPlane)Marshal.PtrToStructure(current, typeof(BoundedPlane));
#pragma warning restore 618
                current = (IntPtr)((long)current + structsize);
            }
            Marshal.FreeCoTaskMem(outArray);
            return(resArray);
        }
        /// <summary>
        /// Iterator block, analyzes surface meshes to find planes and create new 3D cubes to represent each plane.
        /// </summary>
        /// <returns>Yield result.</returns>
        private IEnumerator MakePlanesRoutine()
        {
            // Remove any previously existing planes, as they may no longer be valid.
            for (int index = 0; index < ActivePlanes.Count; index++)
            {
                Destroy(ActivePlanes[index]);
            }

            // Pause our work, and continue on the next frame.
            yield return(null);

            float start = Time.realtimeSinceStartup;

            ActivePlanes.Clear();

            // Get the latest Mesh data from the Spatial Mapping Manager.
            List <PlaneFinding.MeshData> meshData = new List <PlaneFinding.MeshData>();
            List <MeshFilter>            filters  = SpatialMappingManager.Instance.GetMeshFilters();

            for (int index = 0; index < filters.Count; index++)
            {
                MeshFilter filter = filters[index];
                if (filter != null && filter.sharedMesh != null)
                {
                    // fix surface mesh normals so we can get correct plane orientation.
                    filter.mesh.RecalculateNormals();
                    meshData.Add(new PlaneFinding.MeshData(filter));
                }

                if ((Time.realtimeSinceStartup - start) > FrameTime)
                {
                    // Pause our work, and continue to make more PlaneFinding objects on the next frame.
                    yield return(null);

                    start = Time.realtimeSinceStartup;
                }
            }

            // Pause our work, and continue on the next frame.
            yield return(null);

#if !UNITY_EDITOR && UNITY_METRO
            // When not in the unity editor we can use a cool background task to help manage FindPlanes().
            Task <BoundedPlane[]> planeTask = Task.Run(() => PlaneFinding.FindPlanes(meshData, snapToGravityThreshold, MinArea));

            while (planeTask.IsCompleted == false)
            {
                yield return(null);
            }

            BoundedPlane[] planes = planeTask.Result;
#else
            // In the unity editor, the task class isn't available, but perf is usually good, so we'll just wait for FindPlanes to complete.
            BoundedPlane[] planes = PlaneFinding.FindPlanes(meshData, snapToGravityThreshold, MinArea);
#endif

            // Pause our work here, and continue on the next frame.
            yield return(null);

            start = Time.realtimeSinceStartup;

            float maxFloorArea   = 0.0f;
            float maxCeilingArea = 0.0f;
            FloorYPosition   = 0.0f;
            CeilingYPosition = 0.0f;
            float upNormalThreshold = 0.9f;

            if (SurfacePlanePrefab != null && SurfacePlanePrefab.GetComponent <SurfacePlane>() != null)
            {
                upNormalThreshold = SurfacePlanePrefab.GetComponent <SurfacePlane>().UpNormalThreshold;
            }

            // Find the floor and ceiling.
            // We classify the floor as the maximum horizontal surface below the user's head.
            // We classify the ceiling as the maximum horizontal surface above the user's head.
            for (int i = 0; i < planes.Length; i++)
            {
                BoundedPlane boundedPlane = planes[i];
                if (boundedPlane.Bounds.Center.y < 0 && boundedPlane.Plane.normal.y >= upNormalThreshold)
                {
                    maxFloorArea = Mathf.Max(maxFloorArea, boundedPlane.Area);
                    if (maxFloorArea == boundedPlane.Area)
                    {
                        FloorYPosition = boundedPlane.Bounds.Center.y;
                    }
                }
                else if (boundedPlane.Bounds.Center.y > 0 && boundedPlane.Plane.normal.y <= -(upNormalThreshold))
                {
                    maxCeilingArea = Mathf.Max(maxCeilingArea, boundedPlane.Area);
                    if (maxCeilingArea == boundedPlane.Area)
                    {
                        CeilingYPosition = boundedPlane.Bounds.Center.y;
                    }
                }
            }

            // Create SurfacePlane objects to represent each plane found in the Spatial Mapping mesh.
            for (int index = 0; index < planes.Length; index++)
            {
                GameObject   destPlane;
                BoundedPlane boundedPlane = planes[index];

                // Instantiate a SurfacePlane object, which will have the same bounds as our BoundedPlane object.
                if (SurfacePlanePrefab != null && SurfacePlanePrefab.GetComponent <SurfacePlane>() != null)
                {
                    destPlane = Instantiate(SurfacePlanePrefab);
                }
                else
                {
                    destPlane = GameObject.CreatePrimitive(PrimitiveType.Cube);
                    destPlane.AddComponent <SurfacePlane>();
                    destPlane.GetComponent <Renderer>().shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.Off;
                }

                destPlane.transform.parent = planesParent.transform;
                SurfacePlane surfacePlane = destPlane.GetComponent <SurfacePlane>();

                // Set the Plane property to adjust transform position/scale/rotation and determine plane type.
                surfacePlane.Plane = boundedPlane;

                SetPlaneVisibility(surfacePlane);

                if ((destroyPlanesMask & surfacePlane.PlaneType) == surfacePlane.PlaneType)
                {
                    DestroyImmediate(destPlane);
                }
                else
                {
                    // Set the plane to use the same layer as the SpatialMapping mesh.
                    destPlane.layer = SpatialMappingManager.Instance.PhysicsLayer;
                    ActivePlanes.Add(destPlane);
                }

                // 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 making additional planes on the next frame.
                    yield return(null);

                    start = Time.realtimeSinceStartup;
                }
            }

            Debug.Log("Finished making planes.");

            // We are done creating planes, trigger an event.
            EventHandler handler = MakePlanesComplete;
            if (handler != null)
            {
                handler(this, EventArgs.Empty);
            }

            makingPlanes = false;
        }
 private void Awake()
 {
     plane = new BoundedPlane(transform);
 }
 // Used for gameObject initialization.
 private void Start()
 {
     plane = new BoundedPlane();
 }
        /// <summary>
        /// Marshals BoundedPlane data returned from a DLL API call into a managed BoundedPlane array
        /// and then frees the memory that was allocated within the DLL.
        /// </summary>
        /// <remarks>Disabling warning 618 when calling Marshal.SizeOf(), because
        /// Unity does not support .Net 4.5.1+ for using the preferred Marshal.SizeOf(T) method."/>, </remarks>
        private static BoundedPlane[] MarshalBoundedPlanesFromIntPtr(IntPtr outArray, int size)
        {
            BoundedPlane[] resArray = new BoundedPlane[size];
#pragma warning disable 618
            int structsize = Marshal.SizeOf(typeof(BoundedPlane));
#pragma warning restore 618
            IntPtr current = outArray;
            for (int i = 0; i < size; i++)
            {
#pragma warning disable 618
                resArray[i] = (BoundedPlane)Marshal.PtrToStructure(current, typeof(BoundedPlane));
#pragma warning restore 618
                current = (IntPtr)((long)current + structsize);
            }
            Marshal.FreeCoTaskMem(outArray);
            return resArray;
        }
        /// <summary>
        /// Takes the subplanes returned by one or more previous calls to FindSubPlanes() and merges
        /// them together into larger planes that can potentially span across multiple meshes.
        /// Overlapping subplanes that have similar plane equations will be merged together to form
        /// larger planes.
        /// </summary>
        /// <param name="subPlanes">
        /// The output from one or more previous calls to FindSubPlanes().
        /// </param>
        /// <param name="snapToGravityThreshold">
        /// Planes whose normal vectors are within this threshold (in degrees) from vertical/horizontal
        /// will be snapped to be perfectly gravity aligned.  When set to something other than zero, the
        /// bounding boxes for each plane will be gravity aligned as well, rather than rotated for an
        /// optimally tight fit. Pass 0.0 for this parameter to completely disable the gravity alignment
        /// logic.
        /// </param>
        /// <param name="minArea">
        /// While merging subplanes together, any candidate merged plane whose constituent mesh
        /// triangles have a total area less than this threshold are ignored.
        /// </param>
        public static BoundedPlane[] MergeSubPlanes(BoundedPlane[] subPlanes, float snapToGravityThreshold = 0.0f, float minArea = 0.0f)
        {
            StartPlaneFinding();

            try
            {
                int planeCount;
                IntPtr planesPtr;
                DLLImports.MergeSubPlanes(subPlanes.Length, PinObject(subPlanes), minArea, snapToGravityThreshold, out planeCount, out planesPtr);
                return MarshalBoundedPlanesFromIntPtr(planesPtr, planeCount);
            }
            finally
            {
                FinishPlaneFinding();
            }
        }
Beispiel #9
0
 private void Awake()
 {
     plane = new BoundedPlane(transform);
 }