Exemplo n.º 1
0
        /// <summary>
        /// Saves a serialized scene from Scene Understanding to disk as obj files. One obj file is saved per class, i.e. one file for walls, one file for ceilings, etc.
        /// </summary>
        /// <param name="serializedScene">Serialized scene.</param>
        /// <returns>Task.</returns>
        public static async Task SaveObjsToDiskAsync(byte[] serializedScene)
        {
            if (serializedScene == null)
            {
                Logger.LogWarning("SceneUnderstandingSaveDataUtils.SaveObjsToDisk: Nothing to save.");
                return;
            }

            // Deserialize the scene.
            SceneUnderstanding.Scene scene = SceneUnderstanding.Scene.Deserialize(serializedScene);

            // List of all SceneObjectKind enum values.
            List <SceneUnderstanding.SceneObjectKind> sceneObjectKinds = Enum.GetValues(typeof(SceneUnderstanding.SceneObjectKind)).Cast <SceneUnderstanding.SceneObjectKind>().ToList();

            List <Task> tasks = new List <Task>();

            foreach (SceneUnderstanding.SceneObjectKind soKind in sceneObjectKinds)
            {
                tasks.Add(SaveSceneObjectsAsObjAsync(
                              scene.SceneObjects.Where <SceneUnderstanding.SceneObject>(so => so.Kind == soKind),
                              SceneUnderstandingUtils.GetColorForLabel(soKind) == null ? Color.black : SceneUnderstandingUtils.GetColorForLabel(soKind).Value,
                              string.Format("{0}_{1}", GetDefaultFileName(), soKind.ToString())));
            }
            await Task.WhenAll(tasks);
        }
        /// <summary>
        /// Coroutine that spreads the work of displaying scene objects across multiple frames.
        /// </summary>
        /// <returns>IEnumerator.</returns>
        private IEnumerator DisplayData()
        {
            StatusText.Clear();
            StatusText.Append("About to display the latest set of scene objects.");
            StatusText.Append(string.Format("Current Settings:-\n\tRenderSceneObjects: {0}; SceneObjectVisualizationMode: {1}; RenderInferredRegions: {2};\n\tRenderPlatform: {3}; RenderBackground: {4}; RenderUnknown: {5}; RenderCompletelyInferred: {6};\n\tRenderWorldMesh: {7}; WorldMeshLOD: {8};\n\tBoundingSphereRadiusInMeters: {9};",
                                            RenderSceneObjects, SceneObjectVisualizationMode.ToString(), SUDataProvider.RequestInferredRegions, RenderPlatformSceneObjects, RenderBackgroundSceneObjects, RenderUnknownSceneObjects, RenderCompletelyInferredSceneObjects, RenderWorldMesh, SUDataProvider.WorldMeshLOD.ToString(), SUDataProvider.BoundingSphereRadiusInMeters));

            // First, get the latest scene from the data provider.
            Tuple <Guid, byte[]> latestSceneData = SUDataProvider.GetLatestSerializedScene();

            byte[] serializedScene = latestSceneData.Item2;

            if (serializedScene != null)
            {
                // Then, deserialize the scene.
                SceneUnderstanding.Scene scene = SceneUnderstanding.Scene.Deserialize(serializedScene);
                if (scene != null)
                {
                    // This will destroy all game objects under root.
                    SUUtils.DestroyAllGameObjectsUnderParent(SceneRoot.transform);

                    // Return to account for the destruction of the game objects at the end of the frame.
                    yield return(null);

                    // Retrieve the Scene to Unity world transform.
                    System.Numerics.Matrix4x4?sceneToUnityTransform = TransformUtils.GetSceneToUnityTransform(scene.OriginSpatialGraphNodeId, SUDataProvider.RunOnDevice);
                    if (sceneToUnityTransform != null)
                    {
                        // This will place the root object that represents the scene in the right place.
                        TransformUtils.SetUnityTransformFromMatrix4x4(sceneToUnityTransform.Value, SceneRoot.transform);

                        // Retrieve all the scene objects, associated with this scene.
                        IEnumerable <SceneUnderstanding.SceneObject> sceneObjects = scene.SceneObjects;

                        int i = 0;
                        foreach (SceneUnderstanding.SceneObject sceneObject in sceneObjects)
                        {
                            if (DisplaySceneObject(sceneObject))
                            {
                                ++i;
                                if (i % 5 == 0)
                                {
                                    yield return(null);
                                }
                            }
                        }
                    }

                    // When running on PC, orient the main camera such that the floor is on the Unity world's X-Z plane.
                    if (SUDataProvider.RunOnDevice == false)
                    {
                        SUUtils.OrientSceneRootForPC(SceneRoot, scene);
                    }
                }
            }

            StatusText.Append("SceneUnderstandingDisplayManager.DisplayData: Display completed.");
            _displayInProgress      = false;
            _lastDisplayedSceneGuid = latestSceneData.Item1;
        }
        /// <summary>
        /// Orients the root game object, such that the Scene Understanding floor lies on the Unity world's X-Z plane.
        /// </summary>
        /// <param name="sceneRoot">Root game object.</param>
        /// <param name="scene">Scene Understanding scene.</param>
        public void OrientSceneRootForPC(GameObject sceneRoot, SceneUnderstanding.Scene scene)
        {
            if (scene == null)
            {
                Logger.LogWarning("SceneUnderstandingUtils.OrientSceneRootForPC: Scene is null.");
                return;
            }

            IEnumerable <SceneUnderstanding.SceneObject> sceneObjects = scene.SceneObjects;

            float areaForlargestFloorSoFar = 0;

            SceneUnderstanding.SceneObject floorSceneObject = null;
            SceneUnderstanding.SceneQuad   floorQuad        = null;

            // Find the largest floor quad.
            foreach (SceneUnderstanding.SceneObject so in sceneObjects)
            {
                if (so.Kind == SceneUnderstanding.SceneObjectKind.Floor)
                {
                    IEnumerable <SceneUnderstanding.SceneQuad> quads = so.Quads;

                    if (quads != null)
                    {
                        foreach (SceneUnderstanding.SceneQuad quad in quads)
                        {
                            float quadArea = quad.Extents.X * quad.Extents.Y;

                            if (quadArea > areaForlargestFloorSoFar)
                            {
                                areaForlargestFloorSoFar = quadArea;
                                floorSceneObject         = so;
                                floorQuad = quad;
                            }
                        }
                    }
                }
            }

            if (floorQuad != null)
            {
                // Compute the floor quad's normal.
                float widthInMeters  = floorQuad.Extents.X;
                float heightInMeters = floorQuad.Extents.Y;

                System.Numerics.Vector3 point1 = new System.Numerics.Vector3(-widthInMeters / 2, -heightInMeters / 2, 0);
                System.Numerics.Vector3 point2 = new System.Numerics.Vector3(widthInMeters / 2, -heightInMeters / 2, 0);
                System.Numerics.Vector3 point3 = new System.Numerics.Vector3(-widthInMeters / 2, heightInMeters / 2, 0);

                System.Numerics.Matrix4x4 floorTransform = floorSceneObject.GetLocationAsMatrix();
                floorTransform = TransformUtils.ConvertRightHandedMatrix4x4ToLeftHanded(floorTransform);

                System.Numerics.Vector3 tPoint1 = System.Numerics.Vector3.Transform(point1, floorTransform);
                System.Numerics.Vector3 tPoint2 = System.Numerics.Vector3.Transform(point2, floorTransform);
                System.Numerics.Vector3 tPoint3 = System.Numerics.Vector3.Transform(point3, floorTransform);

                System.Numerics.Vector3 p21 = tPoint2 - tPoint1;
                System.Numerics.Vector3 p31 = tPoint3 - tPoint1;

                System.Numerics.Vector3 floorNormal = System.Numerics.Vector3.Cross(p31, p21);

                // Numerics to Unity conversion.
                Vector3 floorNormalUnity = new Vector3(floorNormal.X, floorNormal.Y, floorNormal.Z);

                // Get the rotation between the floor normal and Unity world's up vector.
                Quaternion rotation = Quaternion.FromToRotation(floorNormalUnity, Vector3.up);

                // Apply the rotation to the root, so that the floor is on the Camera's x-z plane.
                sceneRoot.transform.rotation = rotation;
            }
        }