/// <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); }