Ejemplo n.º 1
0
        /// <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;
            }
        }
        /// <summary>
        /// Displays one individual scene object.
        /// </summary>
        /// <param name="sceneObject">Scene Object to display.</param>
        private bool DisplaySceneObject(SceneUnderstanding.SceneObject sceneObject)
        {
            try
            {
                if (sceneObject == null)
                {
                    Logger.LogWarning("SceneUnderstandingDisplayManager.DisplaySceneObject: Scene Object is null.");
                    return(false);
                }

                // Skip the object, if the setting to display that object is set to false.
                if ((RenderSceneObjects == false && sceneObject.Kind != SceneUnderstanding.SceneObjectKind.World) ||
                    (RenderWorldMesh == false && sceneObject.Kind == SceneUnderstanding.SceneObjectKind.World) ||
                    (RenderPlatformSceneObjects == false && sceneObject.Kind == SceneUnderstanding.SceneObjectKind.Platform) ||
                    (RenderBackgroundSceneObjects == false && sceneObject.Kind == SceneUnderstanding.SceneObjectKind.Background) ||
                    (RenderUnknownSceneObjects == false && sceneObject.Kind == SceneUnderstanding.SceneObjectKind.Unknown) ||
                    (RenderCompletelyInferredSceneObjects == false && sceneObject.Kind == SceneUnderstanding.SceneObjectKind.CompletelyInferred))
                {
                    return(false);
                }

                // Create a game object for the scene object, parent it to the root and set it's transform.
                GameObject soGO = SUUtils.CreateGameObject(sceneObject.Kind.ToString(), SceneRoot.transform);
                TransformUtils.SetUnityTransformFromMatrix4x4(TransformUtils.ConvertRightHandedMatrix4x4ToLeftHanded(sceneObject.GetLocationAsMatrix()), soGO.transform, true);

                // This is the new child game object that will contain the meshes, quads, etc.
                GameObject soChildGO = null;

                // Render the world mesh.
                if (sceneObject.Kind == SceneUnderstanding.SceneObjectKind.World)
                {
                    // Get the meshes from the SU API.
                    IEnumerable <SceneUnderstanding.SceneMesh> meshes = sceneObject.Meshes;

                    // Combine all the world meshes into one unity mesh.
                    Mesh unityMesh = SUUtils.GenerateUnityMeshForSceneObjectMeshes(meshes);

                    // Create a game object with the above unity mesh.
                    soChildGO = SUUtils.CreateGameObjectWithMeshComponents(sceneObject.Kind.ToString(), soGO.transform, unityMesh, WorldMeshMaterial, null);
                }
                // Render all other scene objects.
                else
                {
                    Color?color = SceneUnderstandingUtils.GetColorForLabel(sceneObject.Kind);

                    switch (SceneObjectVisualizationMode)
                    {
                    case VisualizationMode.Quad:
                    case VisualizationMode.QuadWithMask:
                    {
                        // Get the quads from the SU API.
                        IEnumerable <SceneUnderstanding.SceneQuad> quads = sceneObject.Quads;

                        // For each quad, generate the unity mesh, create the game object and apply the invalidation mask, if applicable.
                        foreach (SceneUnderstanding.SceneQuad quad in quads)
                        {
                            // Generate the unity mesh for the quad.
                            Mesh unityMesh = SUUtils.GenerateUnityMeshForSceneObjectQuad(quad);

                            // Create a game object with the above unity mesh.
                            soChildGO = SUUtils.CreateGameObjectWithMeshComponents(
                                sceneObject.Kind.ToString(),
                                soGO.transform,
                                unityMesh,
                                SceneObjectVisualizationMode == VisualizationMode.QuadWithMask ? SceneObjectQuadMaterial : SceneObjectMeshMaterial,
                                color);

                            // Apply the invalidation mask.
                            if (SceneObjectVisualizationMode == VisualizationMode.QuadWithMask)
                            {
                                SUUtils.ApplyQuadRegionMask(quad, soChildGO, color);
                            }
                        }
                    }
                    break;

                    case VisualizationMode.Mesh:
                    case VisualizationMode.Wireframe:
                    {
                        // Get the meshes from the SU API.
                        IEnumerable <SceneUnderstanding.SceneMesh> meshes = sceneObject.Meshes;

                        foreach (SceneUnderstanding.SceneMesh mesh in meshes)
                        {
                            // Generate the unity mesh for the Scene Understanding mesh.
                            Mesh unityMesh = SUUtils.GenerateUnityMeshForSceneObjectMesh(mesh);

                            // Create a game object with the above unity mesh.
                            soChildGO = SUUtils.CreateGameObjectWithMeshComponents(
                                sceneObject.Kind.ToString(),
                                soGO.transform,
                                unityMesh,
                                SceneObjectVisualizationMode == VisualizationMode.Mesh ? SceneObjectMeshMaterial : SceneObjectWireframeMaterial,
                                SceneObjectVisualizationMode == VisualizationMode.Mesh ? color : null);
                        }
                    }
                    break;

                    default:
                        break;
                    }
                }

                if (DisplayTextLabels)
                {
                    // Only add text for the labels below.
                    if (sceneObject.Kind == SceneUnderstanding.SceneObjectKind.Ceiling ||
                        sceneObject.Kind == SceneUnderstanding.SceneObjectKind.Floor ||
                        sceneObject.Kind == SceneUnderstanding.SceneObjectKind.Platform ||
                        sceneObject.Kind == SceneUnderstanding.SceneObjectKind.Wall)
                    {
                        SUUtils.AddTextLabel(soChildGO, sceneObject.Kind.ToString(), LabelFont);
                    }
                }

                // When running on device, add a worldanchor component to keep the scene object aligned to the real world.
                // When running on PC, add a boxcollider component, that is used for the 'Focus' functionality (in CameraMovement.cs).
                if (SUDataProvider.RunOnDevice)
                {
                    soGO.AddComponent <UnityEngine.XR.WSA.WorldAnchor>();
                }
                else
                {
                    soGO.AddComponent <BoxCollider>();
                }
            }
            catch (Exception e)
            {
                Logger.LogException(e);
            }
            return(true);
        }