// invoked by AnchorAdded-event private void PlaneAnchorAdded(ARPlaneAnchor arPlaneAnchor) { Debug.Log("Plane added: " + arPlaneAnchor.identifier); GameObject go = null; // if(arManager.displayTrackedSurfaces) // { // go = UnityARUtility.CreatePlaneInScene(arPlaneAnchor); // go.AddComponent<DontDestroyOnLoad>(); // these GOs persist across scene loads // } ARPlaneAnchorGameObject arpag = new ARPlaneAnchorGameObject(); arpag.planeAnchor = arPlaneAnchor; arpag.gameObject = go; planeAnchorDict.Add(arPlaneAnchor.identifier, arpag); trackedPlanesTimestamp = GetLastFrameTimestamp(); // create overlay surfaces as needed if (arManager.useOverlaySurface != MultiARManager.SurfaceRenderEnum.None) { // estimate the material Material surfaceMat = arManager.GetSurfaceMaterial(); int surfaceLayer = MultiARInterop.GetSurfaceLayer(); MultiARInterop.MultiARData arData = arManager.GetARData(); string surfId = arPlaneAnchor.identifier; if (!arData.dictOverlaySurfaces.ContainsKey(surfId)) { GameObject overlaySurfaceObj = new GameObject(); overlaySurfaceObj.name = "surface-" + surfId; overlaySurfaceObj.layer = surfaceLayer; overlaySurfaceObj.transform.SetParent(arData.surfaceRendererRoot ? arData.surfaceRendererRoot.transform : null); // GameObject overlayCubeObj = GameObject.CreatePrimitive(PrimitiveType.Cube); // overlayCubeObj.name = "surface-cube-" + surfId; // overlayCubeObj.transform.localScale = new Vector3(0.2f, 0.2f, 0.2f); // overlayCubeObj.transform.SetParent(overlaySurfaceObj.transform); OverlaySurfaceUpdater overlaySurface = overlaySurfaceObj.AddComponent <OverlaySurfaceUpdater>(); overlaySurface.SetSurfaceMaterial(surfaceMat); overlaySurface.SetSurfaceCollider(arManager.surfaceCollider, arManager.colliderMaterial); arData.dictOverlaySurfaces.Add(surfId, overlaySurface); } // update the surface mesh UpdateOverlaySurface(arData.dictOverlaySurfaces[surfId], arPlaneAnchor); } }
/// <summary> /// Updates existing overlay surfaces with the currently selected material and collider. /// </summary> public void UpdateOverlaySurfaces() { // get current material Material surfaceMat = GetSurfaceMaterial(); foreach (string sKey in arData.dictOverlaySurfaces.Keys) { OverlaySurfaceUpdater surface = arData.dictOverlaySurfaces[sKey]; MeshRenderer meshRenderer = surface.gameObject.GetComponent <MeshRenderer>(); MeshCollider meshCollider = surface.gameObject.GetComponent <MeshCollider>(); // surface renderer if (surfaceMat != null) { if (meshRenderer != null && !meshRenderer.enabled) { meshRenderer.enabled = true; } surface.SetSurfaceMaterial(surfaceMat); } else { if (meshRenderer != null && meshRenderer.enabled) { meshRenderer.enabled = false; } } // surface collider if (surfaceCollider) { if (meshCollider != null && !meshCollider.enabled) { meshCollider.enabled = true; } surface.SetSurfaceCollider(surfaceCollider, colliderMaterial); } else { if (meshCollider != null && meshCollider.enabled) { meshCollider.enabled = false; } } } }
// loads AR scene and the detected surfaces public JsonArScene LoadArScene(string dataFilePath) { if (!File.Exists(dataFilePath)) { return(null); } // load json string sJsonText = File.ReadAllText(dataFilePath); JsonArScene data = JsonUtility.FromJson <JsonArScene>(sJsonText); if (data != null) { if (useSavedHeading) { startHeading = data.startHeading; } Quaternion compStartRot = Quaternion.Euler(0f, -startHeading, 0f); if (data.surfaceSet != null) { // destroy currently loaded surfaces DestroyLoadedSurfaces(); for (int i = 0; i < data.surfaceSet.surfaceCount; i++) { GameObject overlaySurfaceObj = new GameObject(); overlaySurfaceObj.name = "surface-" + i; overlaySurfaceObj.transform.SetParent(transform); OverlaySurfaceUpdater overlaySurface = overlaySurfaceObj.AddComponent <OverlaySurfaceUpdater>(); overlaySurface.SetSurfaceMaterial(surfaceMaterial); overlaySurface.SetSurfaceCollider(true, null); Vector3 surfacePos = data.surfaceSet.surfaces[i].position; surfacePos = compStartRot * surfacePos; Quaternion surfaceRot = Quaternion.Euler(data.surfaceSet.surfaces[i].rotation); surfaceRot = Quaternion.Euler(surfaceRot.eulerAngles + compStartRot.eulerAngles); // List <Vector3> meshVertices = new List <Vector3>(data.surfaceSet.surfaces[i].vertices); List <int> meshIndices = new List <int>(data.surfaceSet.surfaces[i].indices); // update the surface mesh overlaySurface.UpdateSurfaceMesh(surfacePos, surfaceRot, meshVertices, meshIndices); alLoadedSurfaces.Add(overlaySurface); } } if (cameraTransform && data.sceneCam != null) { Vector3 camPos = data.sceneCam.camPos; camPos = compStartRot * camPos; Quaternion camRot = Quaternion.Euler(data.sceneCam.camRot); camRot = Quaternion.Euler(camRot.eulerAngles + compStartRot.eulerAngles); cameraTransform.position = camPos; cameraTransform.rotation = camRot; } if (displaySavedInfos) { if (locationInfoText) { if (data.scenePos != null) { string sMessage = "Lat: " + data.scenePos.lat + ", Lon: " + data.scenePos.lon + ", Alt: " + data.scenePos.alt; sMessage += "\nCompass Head: " + FormatHeading(data.compHeading) + ", Start: " + FormatHeading(data.startHeading); locationInfoText.text = sMessage; } else { locationInfoText.text = "Location service not supported."; } } if (gyroInfoText) { if (data.sceneRot != null) { string sMessage = "Gyro Att: " + data.sceneRot.gyroAtt + ", Rot: " + data.sceneRot.gyroRot; if (data.sceneCam != null) { sMessage += string.Format("\nCamera Pos: {0}, Rot: {1}", data.sceneCam.camPos, data.sceneCam.camRot); } gyroInfoText.text = sMessage; } else { gyroInfoText.text = "Gyroscope not supported."; } } } Debug.Log("AR-Scene (head: " + (int)data.startHeading + ") loaded from: " + dataFilePath); } return(data); }
void Update() { if (!isInitialized) { return; } // check for errors _QuitOnConnectionErrors(); // check for input (touch) CheckForInputAction(); // estimate the tracking state SessionStatus status = Session.Status; if (status.IsError() || status.IsNotInitialized()) { cameraTrackingState = TrackingState.Stopped; return; } else if (status == SessionStatus.Tracking) { cameraTrackingState = TrackingState.Tracking; } else { cameraTrackingState = TrackingState.Paused; } // get frame timestamp and light intensity lastFrameTimestamp = GetCurrentTimestamp(); if (Frame.LightEstimate.State == LightEstimateState.Valid) { // Normalize pixel intensity by middle gray in gamma space. const float middleGray = 0.466f; currentLightIntensity = Frame.LightEstimate.PixelIntensity / middleGray; } // get point cloud, if needed MultiARInterop.MultiARData arData = arManager.GetARData(); if (arManager.usePointCloudData) { if (Frame.PointCloud.PointCount > 0 && Frame.PointCloud.IsUpdatedThisFrame) { // Copy the point cloud points for (int i = 0; i < Frame.PointCloud.PointCount; i++) { PointCloudPoint point = Frame.PointCloud.GetPointAsStruct(i); arData.pointCloudData[i] = new Vector3(point.Position.x, point.Position.y, point.Position.z); } arData.pointCloudLength = Frame.PointCloud.PointCount; arData.pointCloudTimestamp = lastFrameTimestamp; } } // // display the tracked planes if needed // if(arManager.displayTrackedSurfaces && trackedPlanePrefab) // { // // get the new planes // Frame.GetNewPlanes(ref newTrackedPlanes); // // // Iterate over planes found in this frame and instantiate corresponding GameObjects to visualize them. // for (int i = 0; i < newTrackedPlanes.Count; i++) // { // // Instantiate a plane visualization prefab and set it to track the new plane. // GameObject planeObject = Instantiate(trackedPlanePrefab, Vector3.zero, Quaternion.identity); // planeObject.GetComponent<GoogleARCore.HelloAR.TrackedPlaneVisualizer>().SetTrackedPlane(newTrackedPlanes[i]); // // // Apply a random color and grid rotation. // planeObject.GetComponent<Renderer>().material.SetColor("_GridColor", planeColors[Random.Range(0, planeColors.Length - 1)]); // planeObject.GetComponent<Renderer>().material.SetFloat("_UvRotation", Random.Range(0.0f, 360.0f)); // } // } // get all tracked planes Session.GetTrackables <DetectedPlane>(allTrackedPlanes, TrackableQueryFilter.All); // create overlay surfaces as needed if (arManager.useOverlaySurface != MultiARManager.SurfaceRenderEnum.None) { alSurfacesToDelete.Clear(); alSurfacesToDelete.AddRange(arData.dictOverlaySurfaces.Keys); // estimate the material Material surfaceMat = arManager.GetSurfaceMaterial(); int surfaceLayer = MultiARInterop.GetSurfaceLayer(); for (int i = 0; i < allTrackedPlanes.Count; i++) { string surfId = allTrackedPlanes[i].m_TrackableNativeHandle.ToString(); if (!arData.dictOverlaySurfaces.ContainsKey(surfId)) { GameObject overlaySurfaceObj = new GameObject(); overlaySurfaceObj.name = "surface-" + surfId; overlaySurfaceObj.layer = surfaceLayer; overlaySurfaceObj.transform.SetParent(arData.surfaceRendererRoot ? arData.surfaceRendererRoot.transform : null); // GameObject overlayCubeObj = GameObject.CreatePrimitive(PrimitiveType.Cube); // overlayCubeObj.name = "surface-cube-" + surfId; // overlayCubeObj.transform.localScale = new Vector3(0.2f, 0.2f, 0.2f); // overlayCubeObj.transform.SetParent(overlaySurfaceObj.transform); OverlaySurfaceUpdater overlaySurface = overlaySurfaceObj.AddComponent <OverlaySurfaceUpdater>(); overlaySurface.SetSurfaceMaterial(surfaceMat); overlaySurface.SetSurfaceCollider(arManager.surfaceCollider, arManager.colliderMaterial); arData.dictOverlaySurfaces.Add(surfId, overlaySurface); } // update the surface mesh bool bValidSurface = UpdateOverlaySurface(arData.dictOverlaySurfaces[surfId], allTrackedPlanes[i]); if (bValidSurface && alSurfacesToDelete.Contains(surfId)) { alSurfacesToDelete.Remove(surfId); } } // delete not tracked surfaces foreach (string surfId in alSurfacesToDelete) { OverlaySurfaceUpdater overlaySurface = arData.dictOverlaySurfaces[surfId]; arData.dictOverlaySurfaces.Remove(surfId); Destroy(overlaySurface.gameObject); } } // check status of the anchors List <string> alAnchorsToRemove = new List <string>(); foreach (string anchorId in arData.allAnchorsDict.Keys) { List <GameObject> anchoredObjs = arData.allAnchorsDict[anchorId]; foreach (GameObject anchoredObj in anchoredObjs) { Transform parentTrans = anchoredObj.transform.parent; if (parentTrans == null) { if (!alAnchorsToRemove.Contains(anchorId)) { alAnchorsToRemove.Add(anchorId); } anchoredObj.SetActive(false); } else { Anchor anchor = parentTrans.GetComponent <Anchor>(); if (anchor == null || anchor.TrackingState == TrackingState.Stopped) { if (!alAnchorsToRemove.Contains(anchorId)) { alAnchorsToRemove.Add(anchorId); } anchoredObj.transform.parent = null; anchoredObj.SetActive(false); } } } } // remove the stopped anchors from our list foreach (string anchorId in alAnchorsToRemove) { arData.allAnchorsDict.Remove(anchorId); } // clean up alAnchorsToRemove.Clear(); // look for image anchors, if enabled if (arData.imageAnchorsEnabled) { // Get updated augmented images for this frame. Session.GetTrackables <AugmentedImage>(alTrackedAugmentedImages, TrackableQueryFilter.Updated); foreach (var image in alTrackedAugmentedImages) { string sImageName = image.Name; bool wasImageTracked = dictImageAnchors.ContainsKey(sImageName); if (!wasImageTracked && image.TrackingState == TrackingState.Tracking) { // Create an anchor to ensure that ARCore keeps tracking this augmented image. Anchor anchor = image.CreateAnchor(image.CenterPose); anchor.gameObject.name = "ImageAnchor-" + sImageName; DontDestroyOnLoad(anchor.gameObject); alImageAnchorNames.Add(sImageName); dictImageAnchors.Add(sImageName, anchor.gameObject); } else if (wasImageTracked && image.TrackingState == TrackingState.Stopped) { // remove the anchor GameObject anchorObj = dictImageAnchors[sImageName]; alImageAnchorNames.Remove(sImageName); dictImageAnchors.Remove(sImageName); GameObject.Destroy(anchorObj); } } } }
// loads AR scene and the detected surfaces public JsonArScene LoadArScene(string dataFilePath) { if (!File.Exists(dataFilePath)) { return(null); } // load json string sJsonText = File.ReadAllText(dataFilePath); JsonArScene data = JsonUtility.FromJson <JsonArScene>(sJsonText); if (data != null) { Quaternion compStartRot = Quaternion.Euler(0f, -startHeading, 0f); Vector3 camOffset = Vector3.zero; if (applyLocationDistance && locationEnabled && Input.location.status == LocationServiceStatus.Running && data.scenePos != null) { Vector3 locSaved = GeoUtils.LatLong2Meters(data.scenePos.lat, data.scenePos.lon, useLocationAltitude ? data.scenePos.alt : 0f); Vector3 locCamera = GeoUtils.LatLong2Meters(lastLoc.latitude, lastLoc.longitude, useLocationAltitude ? lastLoc.altitude : 0f); camOffset = locSaved - locCamera; camOffset = new Vector3(camOffset.y, camOffset.z, camOffset.x); // x=lon; y=alt; z=lat } if (data.surfaceSet != null) { // destroy currently loaded surfaces DestroyLoadedSurfaces(); for (int i = 0; i < data.surfaceSet.surfaceCount; i++) { GameObject overlaySurfaceObj = new GameObject(); overlaySurfaceObj.name = "surface-" + i; overlaySurfaceObj.transform.SetParent(transform); // GameObject overlayCubeObj = GameObject.CreatePrimitive(PrimitiveType.Cube); // overlayCubeObj.name = "surface-cube-" + i; // overlayCubeObj.transform.localScale = new Vector3(0.1f, 0.2f, 0.3f); // overlayCubeObj.transform.SetParent(overlaySurfaceObj.transform); OverlaySurfaceUpdater overlaySurface = overlaySurfaceObj.AddComponent <OverlaySurfaceUpdater>(); overlaySurface.SetSurfaceMaterial(surfaceMaterial); overlaySurface.SetSurfaceCollider(true, null); Vector3 surfacePos = data.surfaceSet.surfaces[i].position; surfacePos = compStartRot * surfacePos; if (applyLocationDistance) { surfacePos += camOffset; } Quaternion surfaceRot = Quaternion.Euler(data.surfaceSet.surfaces[i].rotation); surfaceRot = Quaternion.Euler(surfaceRot.eulerAngles + compStartRot.eulerAngles); // List <Vector3> meshVertices = new List <Vector3>(data.surfaceSet.surfaces[i].vertices); List <int> meshIndices = new List <int>(data.surfaceSet.surfaces[i].indices); // update the surface mesh overlaySurface.UpdateSurfaceMesh(surfacePos, surfaceRot, meshVertices, meshIndices); // // find the nearest currently tracked surface // MultiARInterop.TrackedSurface[] alTrackedSurf = arManager ? arManager.GetTrackedSurfaces(false) : null; // // MultiARInterop.TrackedSurface nearestSurf; // float nearestDist = float.MaxValue; // bool foundNearestSurf = false; // // if (alTrackedSurf != null && alTrackedSurf.Length > 0) // { // for (int s = 0; s < alTrackedSurf.Length; s++) // { // MultiARInterop.TrackedSurface trackedSurf = alTrackedSurf[s]; // // // } // } alLoadedSurfaces.Add(overlaySurface); } } Debug.Log("AR-Scene (head: " + (int)data.startHeading + ") loaded from: " + dataFilePath); } return(data); }