/// <summary> /// Creates and positions a collection of Placeable space objects on SurfacePlanes in the environment. /// </summary> /// <param name="spaceObjects">Collection of prefab GameObjects that have the Placeable component.</param> /// <param name="surfaces">Collection of SurfacePlane objects in the world.</param> /// <param name="surfaceType">Type of objects and planes that we are trying to match-up.</param> private void CreateSpaceObjects(List <GameObject> spaceObjects, List <GameObject> surfaces, PlacementSurfaces surfaceType) { List <int> UsedPlanes = new List <int>(); // Sort the planes by distance to user. surfaces.Sort((lhs, rhs) => { Vector3 headPosition = Camera.main.transform.position; Collider rightCollider = rhs.GetComponent <Collider>(); Collider leftCollider = lhs.GetComponent <Collider>(); // This plane is big enough, now we will evaluate how far the plane is from the user's head. // Since planes can be quite large, we should find the closest point on the plane's bounds to the // user's head, rather than just taking the plane's center position. Vector3 rightSpot = rightCollider.ClosestPointOnBounds(headPosition); Vector3 leftSpot = leftCollider.ClosestPointOnBounds(headPosition); return(Vector3.Distance(leftSpot, headPosition).CompareTo(Vector3.Distance(rightSpot, headPosition))); }); foreach (GameObject item in spaceObjects) { int index = -1; Collider collider = item.GetComponent <Collider>(); if (surfaceType == PlacementSurfaces.Vertical) { index = FindNearestPlane(surfaces, collider.bounds.size, UsedPlanes, true); } else { index = FindNearestPlane(surfaces, collider.bounds.size, UsedPlanes, false); } // If we can't find a good plane we will put the object floating in space. Vector3 position = Camera.main.transform.position + Camera.main.transform.forward * 2.0f + Camera.main.transform.right * (Random.value - 1.0f) * 2.0f; Quaternion rotation = Quaternion.identity; // If we do find a good plane we can do something smarter. if (index >= 0) { UsedPlanes.Add(index); GameObject surface = surfaces[index]; SurfacePlane plane = surface.GetComponent <SurfacePlane>(); position = surface.transform.position + (plane.PlaneThickness * plane.SurfaceNormal); position = AdjustPositionWithSpatialMap(position, plane.SurfaceNormal); rotation = Camera.main.transform.localRotation; if (surfaceType == PlacementSurfaces.Vertical) { // Vertical objects should face out from the wall. rotation = Quaternion.LookRotation(surface.transform.forward, Vector3.up); } else { // Horizontal objects should face the user. rotation = Quaternion.LookRotation(Camera.main.transform.position); rotation.x = 0f; rotation.z = 0f; } } //Vector3 finalPosition = AdjustPositionWithSpatialMap(position, surfaceType); GameObject spaceObject = Instantiate(item, position, rotation) as GameObject; spaceObject.transform.parent = gameObject.transform; if (spaceObjects.Count == 1) { spaceObject.SendMessage("OnSelect"); } } }
//Used in atof to spawn and place objects on the walls and playfield on the floor. /// <summary> /// Creates and positions a collection of Placeable game objects on SurfacePlanes in the environment. /// </summary> /// <param name="gameObjects">Collection of prefab GameObjects that have the Placeable component.</param> /// <param name="surfaces">Collection of SurfacePlane objects in the world.</param> /// <param name="surfaceType">Type of objects and planes that we are trying to match-up.</param> private void CreateGameObjects(List <GameObject> gameObjects, List <GameObject> surfaces, PlacementSurfaces surfaceType) { List <int> UsedPlanes = new List <int>(); // Sort the planes by distance to user. surfaces.Sort((lhs, rhs) => { Vector3 headPosition = Camera.main.transform.position; Collider rightCollider = rhs.GetComponent <Collider>(); Collider leftCollider = lhs.GetComponent <Collider>(); // This plane is big enough, now we will evaluate how far the plane is from the user's head. // Since planes can be quite large, we should find the closest point on the plane's bounds to the // user's head, rather than just taking the plane's center position. Vector3 rightSpot = rightCollider.ClosestPointOnBounds(headPosition); Vector3 leftSpot = leftCollider.ClosestPointOnBounds(headPosition); return(Vector3.Distance(leftSpot, headPosition).CompareTo(Vector3.Distance(rightSpot, headPosition))); }); foreach (GameObject item in gameObjects) { int index = -1; Collider collider = item.GetComponent <Collider>(); if (surfaceType == PlacementSurfaces.Vertical) { index = FindNearestPlane(surfaces, collider.bounds.size, UsedPlanes, true); } else { index = FindNearestPlane(surfaces, collider.bounds.size, UsedPlanes, false); } // If we can't find a good plane could put the object floating in space. (then we can instantiate it or not, see ending of the code) Vector3 position = Camera.main.transform.position + Camera.main.transform.forward * 2.0f + Camera.main.transform.right * (Random.value - 1.0f) * 2.0f; Quaternion rotation = Quaternion.identity; // If we do find a good plane we can do something smarter. if (index >= 0) { UsedPlanes.Add(index); //We spawn only one object for each plane (for example, for each wall), in the nearest point of it wrt the player GameObject surface = surfaces[index]; SurfacePlane plane = surface.GetComponent <SurfacePlane>(); position = surface.transform.position + (plane.PlaneThickness * plane.SurfaceNormal); position = AdjustPositionWithSpatialMap(position, plane.SurfaceNormal); rotation = Camera.main.transform.localRotation; if (surfaceType == PlacementSurfaces.Vertical) { // Vertical objects should face out from the wall. rotation = Quaternion.LookRotation(surface.transform.forward, Vector3.up); } else { // Horizontal objects should face the user. rotation = Quaternion.LookRotation(Camera.main.transform.position); rotation.x = 0f; rotation.z = 0f; } } //Vector3 finalPosition = AdjustPositionWithSpatialMap(position, surfaceType); //If it's the Playfield, we don't instantiate any prefab (the game object is already in hierarchy), we position it . if (item.CompareTag("Playfield")) { item.transform.position = position; //I case I would want to spawn directly the playfield exactly where the player is (without considering anything else), slightly different from previous method //float yfloorPosition = position.y; //item.transform.position = new Vector3(Camera.main.transform.position.x, yfloorPosition, Camera.main.transform.position.z); List <GameObject> tables = new List <GameObject>(); tables = SurfaceMeshesToPlanes.Instance.GetActivePlanes(PlaneTypes.Table); //Deactivating tables (useful just to avoid Playfield is placed inside them) to not see them anymore foreach (GameObject table in tables) { table.layer = 10; //We set the layer to IGNORE GAZE, in this way even if there are unexpected problems (colliders of tables detected by gaze) we ignore them setting this layer table.SetActive(false); } //item.transform.rotation = rotation; Vector3 relativeDistance = position - Camera.main.transform.position; Quaternion playfieldNewRotation = Quaternion.LookRotation(relativeDistance); playfieldNewRotation.x = 0f; playfieldNewRotation.z = 0f; item.transform.rotation = playfieldNewRotation; if (item.activeInHierarchy == false) { item.SetActive(true); } } //Here we decide if we want to instantiate the object only if we found a good plane (case index>=0) or anyway (in this last case you should remove the "else if" and leave just "Else") else if (index >= 0) { //Standard procedure to instantiate the prefabs GameObject gameItemObject = Instantiate(item, position, rotation) as GameObject; gameItemObject.transform.parent = gameObject.transform; if (gameItemObject.GetComponent <Placeable>().PlacementSurface == PlacementSurfaces.Vertical) { spawnedWallsObjects.Add(gameItemObject); } else if (gameItemObject.GetComponent <Placeable>().PlacementSurface == PlacementSurfaces.Horizontal) { spawnedFloorObjects.Add(gameItemObject); } } else if (index == -1) { //Due to the fact these are just decoration objects, if we can't find a plane to fit the objects, we don't instantiate them //Debug.Log("The object/decoration " + item.name + " could not be instantiated because there's no good plane that fits it (or they all have been already used to instantiate other objects)"); } } }
/// <summary> /// Creates and positions a collection of Placeable space objects on SurfacePlanes in the environment. /// </summary> /// <param name="spaceObjects">Collection of prefab GameObjects that have the Placeable component.</param> /// <param name="surfaces">Collection of SurfacePlane objects in the world.</param> /// <param name="surfaceType">Type of objects and planes that we are trying to match-up.</param> private bool CreateSpaceObjects(GameObject spaceObjects, List <GameObject> surfaces, PlacementSurfaces surfaceType) { List <int> UsedPlanes = new List <int>(); // Sort the planes by distance to user. surfaces.Sort((lhs, rhs) => { Vector3 headPosition = Camera.main.transform.position; Collider rightCollider = rhs.GetComponent <Collider>(); Collider leftCollider = lhs.GetComponent <Collider>(); // This plane is big enough, now we will evaluate how far the plane is from the user's head. // Since planes can be quite large, we should find the closest point on the plane's bounds to the // user's head, rather than just taking the plane's center position. Vector3 rightSpot = rightCollider.ClosestPointOnBounds(headPosition); Vector3 leftSpot = leftCollider.ClosestPointOnBounds(headPosition); return(Vector3.Distance(leftSpot, headPosition).CompareTo(Vector3.Distance(rightSpot, headPosition))); }); debug.text = "" + (int)minAngle; // If we can't find a good plane we will put the object floating in space. Vector3 position = Camera.main.transform.position + Camera.main.transform.forward * 2.0f + Camera.main.transform.right * (Random.value - 1.0f) * 2.0f; while (UsedPlanes.Count < surfaces.Count) { int index = -1; Collider collider = spaceObjects.GetComponent <Collider> (); index = FindNearestPlane(surfaces, collider.bounds.size, UsedPlanes, false); // If we do find a good plane we can do something smarter. if (index >= 0) { UsedPlanes.Add(index); GameObject surface = surfaces [index]; SurfacePlane plane = surface.GetComponent <SurfacePlane> (); position = surface.transform.position + (plane.PlaneThickness * plane.SurfaceNormal); position = AdjustPositionWithSpatialMap(position, plane.SurfaceNormal); //Check angle Vector3 targetDir = position - Camera.main.transform.position; float angle = Vector3.Angle(targetDir, Camera.main.transform.forward); if (Mathf.Abs(angle) < minAngle) { minAngle = Mathf.Abs(angle); debug.text = "" + (int)minAngle; } float angleDelta = 15; if (totalAttempts >= 3) { angleDelta = 360; } if (Mathf.Abs(angle) <= angleDelta) { // Horizontal objects should face the user. PlacePlayground(position); debug.text = "angle placed = " + (int)minAngle; return(true); } // } else { if (totalAttempts >= 3) { PlacePlayground(position); debug.text = "placed in the air"; return(true); } return(false); } } if (totalAttempts >= 3) { PlacePlayground(position); debug.text = "placed in the air"; return(true); } return(false); }
/// <summary> /// Creates and positions a collection of Placeable space objects on SurfacePlanes in the environment. /// </summary> /// <param name="spaceObjects">Collection of prefab GameObjects that have the Placeable component.</param> /// <param name="surfaces">Collection of SurfacePlane objects in the world.</param> /// <param name="surfaceType">Type of objects and planes that we are trying to match-up.</param> private void CreateWidgets(List <GameObject> widgets, List <GameObject> surfaces, PlacementSurfaces surfaceType) { InstantiateWidgetsWithCalculatedPlacement(widgets, surfaces, surfaceType); }
// Update is called once per frame void Update() { switch (mode) { case Mode.AlignLookAt: if (psm.meshesProcessed) { List <GameObject> vertical = new List <GameObject>(); List <GameObject> horizontal = new List <GameObject>(); horizontal = SurfaceMeshesToPlanes.Instance.GetActivePlanes(PlaneTypes.Table); vertical = SurfaceMeshesToPlanes.Instance.GetActivePlanes(PlaneTypes.Wall); if (vertical.Count > 0) { PlacementSurfaces surfaceType = PlacementSurfaces.Vertical; vertical.Sort((lhs, rhs) => { Vector3 headPosition = Camera.main.transform.position; Collider rightCollider = rhs.GetComponent <Collider>(); Collider leftCollider = lhs.GetComponent <Collider>(); // This plane is big enough, now we will evaluate how far the plane is from the user's head. // Since planes can be quite large, we should find the closest point on the plane's bounds to the // user's head, rather than just taking the plane's center position. Vector3 rightSpot = rightCollider.ClosestPointOnBounds(headPosition); Vector3 leftSpot = leftCollider.ClosestPointOnBounds(headPosition); return(Vector3.Distance(leftSpot, headPosition).CompareTo(Vector3.Distance(rightSpot, headPosition))); }); int index = -1; Collider collider = gameObject.GetComponent <Collider>(); index = FindNearestPlane(vertical, collider.bounds.size); Quaternion rotation = Quaternion.identity; if (index >= 0) { GameObject surface = vertical[index]; SurfacePlane plane = surface.GetComponent <SurfacePlane>(); #if DEBUG Debug.Log("Wall's surface normal with respect to starting camera direction: " + plane.SurfaceNormal); #endif aligned_forward = surface.transform.forward; if (!SpatialMappingManager.Instance.IsObserverRunning()) { // If running, Stop the observer by calling // StopObserver() on the SpatialMappingManager.Instance. SpatialMappingManager.Instance.StartObserver(); } GameObject SpatialProcessing = GameObject.Find("SpatialProcessing"); SpatialProcessing.SetActive(false); dbtext.text = "Tap anywhere to finish scanning"; mode = Mode.ContinueScanning; } } } break; case Mode.ContinueScanning: //Now it is waiting for a Tap event to happen. A state change will occur in the OnInputClicked function if mode equals to Mode.ContinueScanning break; case Mode.Placing: if (!ttp.IsBeingPlaced) { WorldAnchorManager.Instance.RemoveAnchor(gameObject); speechRecognition.SetActive(true); //transform.rotation = Quaternion.LookRotation(aligned_forward, Vector3.up); mode = Mode.SetRotation; } break; case Mode.SetRotation: Quaternion tmp = Quaternion.LookRotation(aligned_forward, Vector3.up); gameObject.transform.rotation = Quaternion.Euler(ttp.initial_rotation) * Quaternion.LookRotation(aligned_forward, Vector3.up); mode = Mode.Tuning; break; case Mode.Tuning: Tune(); break; } UnityEngine.XR.WSA.HolographicSettings.SetFocusPointForFrame(transform.position - Camera.main.transform.position); }
/// <summary> /// Creates and positions a collection of Placeable space objects on SurfacePlanes in the environment. /// </summary> /// <param name="spaceObjects">Collection of prefab GameObjects that have the Placeable component.</param> /// <param name="surfaces">Collection of SurfacePlane objects in the world.</param> /// <param name="surfaceType">Type of objects and planes that we are trying to match-up.</param> private void CreateSpaceObjects(List <GameObject> spaceObjects, List <GameObject> surfaces, PlacementSurfaces surfaceType) { List <int> UsedPlanes = new List <int>(); // Sort the planes by distance to user. surfaces.Sort((lhs, rhs) => { Vector3 headPosition = Camera.main.transform.position; Collider rightCollider = rhs.GetComponent <Collider>(); Collider leftCollider = lhs.GetComponent <Collider>(); // This plane is big enough, now we will evaluate how far the plane is from the user's head. // Since planes can be quite large, we should find the closest point on the plane's bounds to the // user's head, rather than just taking the plane's center position. /// Самая близкая точка на границе плоскости к голове пользователя. Vector3 rightSpot = rightCollider.ClosestPointOnBounds(headPosition); Vector3 leftSpot = leftCollider.ClosestPointOnBounds(headPosition); return(Vector3.Distance(leftSpot, headPosition).CompareTo(Vector3.Distance(rightSpot, headPosition))); }); for (int i = 0; i < spaceObjects.Count; i++) { int index = -1; Collider collider = spaceObjects[i].GetComponent <Collider>(); if (surfaceType == PlacementSurfaces.Vertical) { // => ? index = FindNearestPlane(surfaces, collider.bounds.size, UsedPlanes, true); } else { index = FindNearestPlane(surfaces, collider.bounds.size, UsedPlanes, false); } // If we can't find a good plane we will put the object floating in space. Vector3 position = Camera.main.transform.position + Camera.main.transform.forward * 2.0f + Camera.main.transform.right * (Random.value - 1.0f) * 2.0f; Quaternion rotation = Quaternion.identity; // If we do find a good plane we can do something smarter. if (index >= 0) { UsedPlanes.Add(index); // Приравниваем к новой ссылке GameObject'а плоскость из списка, которая прошла проверку, т.е. переменная "index" является номером подходящей плосоксти. GameObject surface = surfaces[index]; SurfacePlane plane = surface.GetComponent <SurfacePlane>(); position = surface.transform.position + (plane.PlaneThickness * plane.SurfaceNormal); position = AdjustPositionWithSpatialMap(position, plane.SurfaceNormal); rotation = Camera.main.transform.localRotation; if (surfaceType == PlacementSurfaces.Vertical) { // Vertical objects should face out from the wall. rotation = Quaternion.LookRotation(surface.transform.forward, Vector3.up); } else { // Horizontal objects should face the user. rotation = Quaternion.LookRotation(Camera.main.transform.position); rotation.x = 0f; rotation.z = 0f; } } if (i == 0 && surfaceType == PlacementSurfaces.Horizontal) { overrideObject.transform.position = position + new Vector3(0.0f, 0.2f, 0.0f); overrideObject.SetActive(true); } else { //Vector3 finalPosition = AdjustPositionWithSpatialMap(position, surfaceType); GameObject spaceObject = Instantiate(spaceObjects[i], position, rotation) as GameObject; spaceObject.transform.parent = gameObject.transform; } } /* * foreach (GameObject item in spaceObjects) * { * int index = -1; * Collider collider = item.GetComponent<Collider>(); * * if (surfaceType == PlacementSurfaces.Vertical) * { * // => ? * index = FindNearestPlane(surfaces, collider.bounds.size, UsedPlanes, true); * } * else * { * index = FindNearestPlane(surfaces, collider.bounds.size, UsedPlanes, false); * } * * // If we can't find a good plane we will put the object floating in space. * Vector3 position = Camera.main.transform.position + Camera.main.transform.forward * 2.0f + Camera.main.transform.right * (Random.value - 1.0f) * 2.0f; * Quaternion rotation = Quaternion.identity; * * // If we do find a good plane we can do something smarter. * if (index >= 0) * { * UsedPlanes.Add(index); * // Приравниваем к новой ссылке GameObject'а плоскость из списка, которая прошла проверку, т.е. переменная "index" является номером подходящей плосоксти. * GameObject surface = surfaces[index]; * SurfacePlane plane = surface.GetComponent<SurfacePlane>(); * position = surface.transform.position + (plane.PlaneThickness * plane.SurfaceNormal); * position = AdjustPositionWithSpatialMap(position, plane.SurfaceNormal); * rotation = Camera.main.transform.localRotation; * * if (surfaceType == PlacementSurfaces.Vertical) * { * // Vertical objects should face out from the wall. * rotation = Quaternion.LookRotation(surface.transform.forward, Vector3.up); * } * else * { * // Horizontal objects should face the user. * rotation = Quaternion.LookRotation(Camera.main.transform.position); * rotation.x = 0f; * rotation.z = 0f; * } * } * * //Vector3 finalPosition = AdjustPositionWithSpatialMap(position, surfaceType); * GameObject spaceObject = Instantiate(item, position, rotation) as GameObject; * spaceObject.transform.parent = gameObject.transform; * } */ }