Tengo una pregunta sobre AR (Realidad Aumentada).
Quiero saber cómo mostrar la información de distancia (como el medidor central...) entre la cámara AR y el objeto de destino. (usando un teléfono inteligente)
¿Puedo hacer eso en Unity? ¿Debo usar AR Foundation? y con ARcore? ¿Cómo escribir código?
Traté de encontrar un código relativo (a continuación), pero parece que se está imprimiendo información entre objeto y objeto, nada sobre "cámara AR"...
var other : Transform; if (other) { var dist = Vector3.Distance(other.position, transform.position); print ("Distance to other: " + dist); }¡Gracias de nuevo!
Aquí se explica cómo hacerlo Unity y AR Foundation 4.1. Este script de ejemplo imprime la profundidad en metros en el centro de la textura de profundidad y funciona tanto con ARCore como con ARKit:
using System; using System.Collections; using UnityEngine; using UnityEngine.Assertions; using UnityEngine.XR.ARFoundation; using UnityEngine.XR.ARSubsystems; public class GetDepthOfCenterPixel : MonoBehaviour { // assign this field in inspector [SerializeField] AROcclusionManager manager = null; IEnumerator Start() { while (ARSession.state < ARSessionState.SessionInitializing) { // manager.descriptor.supportsEnvironmentDepthImage will return a correct value if ARSession.state >= ARSessionState.SessionInitializing yield return null; } if (!manager.descriptor.supportsEnvironmentDepthImage) { Debug.LogError("!manager.descriptor.supportsEnvironmentDepthImage"); yield break; } while (true) { if (manager.TryAcquireEnvironmentDepthCpuImage(out var cpuImage) && cpuImage.valid) { using (cpuImage) { Assert.IsTrue(cpuImage.planeCount == 1); var plane = cpuImage.GetPlane(0); var dataLength = plane.data.Length; var pixelStride = plane.pixelStride; var rowStride = plane.rowStride; Assert.AreEqual(0, dataLength % rowStride, "dataLength should be divisible by rowStride without a remainder"); Assert.AreEqual(0, rowStride % pixelStride, "rowStride should be divisible by pixelStride without a remainder"); var numOfRows = dataLength / rowStride; var centerRowIndex = numOfRows / 2; var centerPixelIndex = rowStride / (pixelStride * 2); var centerPixelData = plane.data.GetSubArray(centerRowIndex * rowStride + centerPixelIndex * pixelStride, pixelStride); var depthInMeters = convertPixelDataToDistanceInMeters(centerPixelData.ToArray(), cpuImage.format); print($"depth texture size: ({cpuImage.width},{cpuImage.height}), pixelStride: {pixelStride}, rowStride: {rowStride}, pixel pos: ({centerPixelIndex}, {centerRowIndex}), depthInMeters of the center pixel: {depthInMeters}"); } } yield return null; } } float convertPixelDataToDistanceInMeters(byte[] data, XRCpuImage.Format format) { switch (format) { case XRCpuImage.Format.DepthUint16: return BitConverter.ToUInt16(data, 0) / 1000f; case XRCpuImage.Format.DepthFloat32: return BitConverter.ToSingle(data, 0); default: throw new Exception($"Format not supported: {format}"); } } }También estoy trabajando en la imagen de profundidad AR y la idea básica es:
Al hacer esto a través de todos los píxeles, puede crear una imagen de profundidad y almacenarla como jpg u otros formatos, aquí está el código de muestra del uso de AR Engine para obtener la distancia:
try (Image depthImage = arFrame.acquireDepthImage()) { int imwidth = depthImage.getWidth(); int imheight = depthImage.getHeight(); Image.Plane plane = depthImage.getPlanes()[0]; ShortBuffer shortDepthBuffer = plane.getBuffer().asShortBuffer(); File sdCardFile = Environment.getExternalStorageDirectory(); Log.i(TAG, "The storage path is " + sdCardFile); File file = new File(sdCardFile, "RawdepthImage.jpg"); Bitmap disBitmap = Bitmap.createBitmap(imwidth, imheight, Bitmap.Config.RGB_565); for (int i = 0; i < imheight; i++) { for (int j = 0; j < imwidth; j++) { int index = (i * imwidth + j) ; shortDepthBuffer.position(index); short depthSample = shortDepthBuffer.get(); short depthRange = (short) (depthSample & 0x1FFF); //If you only want the distance value, here it is byte value = (byte) depthRange; byte value = (byte) depthRange ; disBitmap.setPixel(j, i, Color.rgb(value, value, value)); } } //I rotate the image for a better view Matrix matrix = new Matrix(); matrix.setRotate(90); Bitmap rotatedBitmap = Bitmap.createBitmap(disBitmap, 0, 0, imwidth, imheight, matrix, true); try { FileOutputStream out = new FileOutputStream(file); rotatedBitmap.compress(Bitmap.CompressFormat.JPEG, 90, out); out.flush(); out.close(); MainActivity.num++; } catch (Exception e) { e.printStackTrace(); } } catch (Exception e) { e.printStackTrace(); } }Si bien las respuestas son excelentes, pueden ser demasiado complicadas y avanzadas para esta pregunta, que trata sobre la distancia entre la ARCamera y otro objeto, y no sobre la profundidad de los píxeles y su oclusión.
transform.position le da la posición de cualquier objeto de juego al que adjunte el script en la jerarquía. Así que adjunte el script al objeto ARCamera. Y obviamente, other debe ser el objeto de destino.
Alternativamente, puede obtener referencias a los dos objetos del juego usando variables de inspector o GetComponent