// Raycast from screen space to world space // The GetWorldPositionAtPixel function is innacurate when using ZED_Rig_Mono for some reason. May be a bug with the Unity plugin. // Raycast from the camera in the direction of the world space position we determined from the provided screen space position public RaycastHit raycastFromScreenSpace(Vector2 screenPosition, ZEDManager manager) { Camera leftcamera = manager.GetLeftCamera(); RaycastHit hit; int raycastLength = 20; Vector3 worldPos; ZEDSupportFunctions.GetWorldPositionAtPixel(zedCamera, screenPosition, leftcamera, out worldPos); Vector3 direction = (worldPos - leftcamera.transform.position).normalized; // Debug.DrawRay(leftcamera.transform.position, direction * raycastLength, Color.green, 30f); Physics.Raycast(leftcamera.transform.position, direction * raycastLength, out hit); return(hit); }
// Update is called once per frame void Update() { if (!sl.ZEDCamera.GetInstance().IsCameraReady) { return; } if (Input.GetMouseButtonDown(0)) { /// Mouse Input gives the screen pixel position Vector2 ScreenPosition = Input.mousePosition; Vector3 Normal; Vector3 WorldPos; // Get Normal and real world position defined by the pixel ZEDSupportFunctions.GetNormalAtPixel(ScreenPosition, sl.REFERENCE_FRAME.WORLD, LeftCamera, out Normal); ZEDSupportFunctions.GetWorldPositionAtPixel(ScreenPosition, LeftCamera, out WorldPos); // To consider the location as a floor, we check that the normal is valid and is closely aligned with the gravity bool validFloor = Normal.x != float.NaN && Vector3.Dot(Normal, Vector3.up) > 0.85f; // If we've found a floor to place the bunny, then set its location and show it. if (validFloor) { GameObject newbunny = Instantiate(Object); newbunny.transform.localPosition = WorldPos; newbunny.transform.LookAt(new Vector3(ZedManager.transform.position.x, newbunny.transform.position.y, ZedManager.transform.position.z), Vector3.up); newbunny.SetActive(true); } else { if (Normal.x == float.NaN) { Debug.Log("cannot place object at this position. Normal vector not detected."); } if (Vector3.Dot(Normal, Vector3.up) <= 0.85f) { Debug.Log("cannot place object at this position. Normal vector angled too far from up: " + Mathf.Acos(Vector3.Dot(Normal, Vector3.up)) * Mathf.Rad2Deg + "°"); } Object.SetActive(false); } } }
// Update is called once per frame void Update() { if (!zedManager.zedCamera.IsCameraReady) { return; } if (Input.GetMouseButtonDown(0)) //Checks for left click. { /// Mouse Input gives the screen pixel position Vector2 ScreenPosition = Input.mousePosition; //Get Normal and real world position defined by the pixel . Vector3 Normal; Vector3 WorldPos; ZEDSupportFunctions.GetNormalAtPixel(zedManager.zedCamera, ScreenPosition, sl.REFERENCE_FRAME.WORLD, LeftCamera, out Normal); ZEDSupportFunctions.GetWorldPositionAtPixel(zedManager.zedCamera, ScreenPosition, LeftCamera, out WorldPos); //To consider the location as a flat surface, we check that the normal is valid and is closely aligned with gravity. bool validFloor = Normal.x != float.NaN && Vector3.Dot(Normal, Vector3.up) > 0.85f; //If we've found a floor to place the object, spawn a copy of the prefab. if (validFloor) { GameObject newgo = Instantiate(ObjectToPlace); newgo.transform.localPosition = WorldPos; newgo.transform.LookAt(new Vector3(zedManager.transform.position.x, newgo.transform.position.y, zedManager.transform.position.z), Vector3.up); } else { if (Normal.x == float.NaN) { Debug.Log("Cannot place object at this position. Normal vector not detected."); } if (Vector3.Dot(Normal, Vector3.up) <= 0.85f) { Debug.Log("Cannot place object at this position. Normal vector angled too far from up: " + Mathf.Acos(Vector3.Dot(Normal, Vector3.up)) * Mathf.Rad2Deg + "°"); } } } }
/// <summary> /// Looks for a random point in a radius around itself. /// Upon collision, the point is moved slightly towards the camera and if its too far it's set to "maxSpawnDistance". /// A more thorough search is then done for any other obstacles around it, also, in a radius. /// If the number of collision doesn't exeeds the set threshold, then return true and output the new position. /// </summary> /// <returns><c>true</c>, if random spawn location was checked, <c>false</c> otherwise.</returns> /// <param name="newRandomPos">Random position.</param> private bool CheckRandomSpawnLocation(out Vector3 newRandomPos) { //We can't do anything if the ZED isn't initialized. if (!zedManager.IsZEDReady) { newRandomPos = Vector3.zero; return(false); } //Pick a screen position at random between 0.25 and 0.75. Vector2 randomScreenPoint = new Vector2(Random.Range(0.25f, 0.75f) * Screen.width, Random.Range(0.25f, 0.75f) * Screen.height); //Get the world position of that position in the real world Vector3 randomWorldPoint; bool foundWorldPoint = ZEDSupportFunctions.GetWorldPositionAtPixel(zedManager.zedCamera, randomScreenPoint, leftcamera, out randomWorldPoint); if (!foundWorldPoint) //We can't read depth from that point. { newRandomPos = Vector3.zero; return(false); } float firstDistance = Vector3.Distance(leftcamera.transform.position, randomWorldPoint); float newClearRadius; //Check that the distance isn't too far. if (firstDistance > maxSpawnDistance) { newClearRadius = firstDistance - maxSpawnDistance; } else { newClearRadius = clearRadius; } //If we spawn the drone at that world point, it'll spawn inside a wall. Bring it between you and that wall. Quaternion directionToCamera = Quaternion.LookRotation(leftcamera.transform.position - randomWorldPoint, Vector3.up); Vector3 closerWorldPoint = randomWorldPoint + directionToCamera * Vector3.forward * newClearRadius; //Check that distance isn't too close float secondDistance = Vector3.Distance(leftcamera.transform.position, closerWorldPoint); if (secondDistance < 1f) { newRandomPos = Vector3.zero; return(false); } //Also check nearby points in a sphere of radius=ClearRadius to make sure the whole drone has a clear space. if (ZEDSupportFunctions.HitTestOnSphere(zedManager.zedCamera, leftcamera, closerWorldPoint, 1f, radiusCheckRate, percentagethreshold)) { //Not clear. newRandomPos = Vector3.zero; return(false); } else { //Clear. newRandomPos = closerWorldPoint; return(true); } }