Advertisement
Guest User

Untitled

a guest
Oct 16th, 2019
119
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 13.58 KB | None | 0 0
  1. public class AR_Activity extends AppCompatActivity implements GLSurfaceView.Renderer {
  2.  
  3. private static final String TAG = AR_Activity.class.getSimpleName();
  4.  
  5. // Rendering. The Renderers are created here, and initialized when the GL surface is created.
  6. private GLSurfaceView surfaceView;
  7.  
  8. private final SBH messageSnackbarHelper = new SBH();
  9. private DRH displayRotationHelper;
  10. private final TSH trackingStateHelper = new TSH(this);
  11. private TH tapHelper;
  12.  
  13. private final BGRenderer backgroundRenderer = new BGRenderer();
  14. private final OBJRenderer virtualObject = new OBJRenderer();
  15. //private final OBJRenderer virtualObjectShadow = new OBJRenderer();
  16. private final PlaneRenderer planeRenderer = new PlaneRenderer();
  17. private final PCRenderer pointCloudRenderer = new PCRenderer();
  18.  
  19. // Temporary matrix allocated here to reduce number of allocations for each frame.
  20. private final float[] anchorMatrix = new float[16];
  21. //private static final float[] DEFAULT_COLOR = new float[] {0f, 0f, 0f, 0f};
  22.  
  23. private static final String SEARCHING_PLANE_MESSAGE = "Searching for surfaces...";
  24.  
  25. @Override
  26. public void onWindowFocusChanged(boolean hasFocus) {
  27. super.onWindowFocusChanged(hasFocus);
  28. FSH.setFullScreenOnWindowFocusChanged(this, hasFocus);
  29. }
  30.  
  31. @Override
  32. public void onSurfaceCreated(GL10 gl10, EGLConfig eglConfig) {
  33. GLES20.glClearColor(0.1f, 0.1f, 0.1f, 1.0f);
  34.  
  35. // Prepare the rendering objects. This involves reading shaders, so may throw an IOException.
  36. try {
  37. // Create the texture and pass it to ARCore session to be filled during update().
  38. backgroundRenderer.createOnGlThread(/*context=*/ this);
  39. planeRenderer.createOnGlThread(/*context=*/ this, "models/trigrid.png");
  40. pointCloudRenderer.createOnGlThread(/*context=*/ this);
  41.  
  42. virtualObject.createOnGlThread(/*context=*/ this, "models/andy.obj", "models/andy.png");
  43. virtualObject.setMaterialProperties(0.0f, 2.0f, 0.5f, 6.0f);
  44.  
  45. //virtualObjectShadow.createOnGlThread(
  46. // /*context=*/ this, "models/andy_shadow.obj", "models/andy_shadow.png");
  47. //virtualObjectShadow.setBlendMode(OBJRenderer.BlendMode.Shadow);
  48. //virtualObjectShadow.setMaterialProperties(1.0f, 0.0f, 0.0f, 1.0f);
  49.  
  50. } catch (IOException e) {
  51. Log.e(TAG, "Failed to read an asset file", e);
  52. }
  53. }
  54.  
  55. @Override
  56. public void onSurfaceChanged(GL10 gl10, int width, int height) {
  57. displayRotationHelper.onSurfaceChanged(width, height);
  58. GLES20.glViewport(0, 0, width, height);
  59. }
  60.  
  61. @Override
  62. public void onDrawFrame(GL10 gl10) {
  63. // Clear screen to notify driver it should not load any pixels from previous frame.
  64. GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);
  65.  
  66. if (arSession == null) {
  67. return;
  68. }
  69. // Notify ARCore session that the view size changed so that the perspective matrix and
  70. // the video background can be properly adjusted.
  71. displayRotationHelper.updateSessionIfNeeded(arSession);
  72.  
  73. try {
  74. arSession.setCameraTextureName(backgroundRenderer.getTextureId());
  75.  
  76. // Obtain the current frame from ARSession. When the configuration is set to
  77. // UpdateMode.BLOCKING (it is by default), this will throttle the rendering to the
  78. // camera frame rate.
  79. Frame frame = arSession.update();
  80. Camera camera = frame.getCamera();
  81.  
  82. // Handle one tap per frame.
  83. handleTap(frame, camera);
  84.  
  85. // If frame is ready, render camera preview image to the GL surface.
  86. backgroundRenderer.draw(frame);
  87.  
  88. // Keep the screen unlocked while tracking, but allow it to lock when tracking stops.
  89. trackingStateHelper.updateKeepScreenOnFlag(camera.getTrackingState());
  90.  
  91. // If not tracking, don't draw 3D objects, show tracking failure reason instead.
  92. if (camera.getTrackingState() == TrackingState.PAUSED) {
  93. messageSnackbarHelper.showMessage(
  94. this, TSH.getTrackingFailureReasonString(camera));
  95. return;
  96. }
  97.  
  98. // Get projection matrix.
  99. float[] projmtx = new float[16];
  100. camera.getProjectionMatrix(projmtx, 0, 0.1f, 100.0f);
  101.  
  102. // Get camera matrix and draw.
  103. float[] viewmtx = new float[16];
  104. camera.getViewMatrix(viewmtx, 0);
  105.  
  106. // Compute lighting from average intensity of the image.
  107. // The first three components are color scaling factors.
  108. // The last one is the average pixel intensity in gamma space.
  109. final float[] colorCorrectionRgba = new float[4];
  110. frame.getLightEstimate().getColorCorrection(colorCorrectionRgba, 0);
  111.  
  112. // Visualize tracked points.
  113. // Use try-with-resources to automatically release the point cloud.
  114. try (PointCloud pointCloud = frame.acquirePointCloud()) {
  115. pointCloudRenderer.update(pointCloud);
  116. pointCloudRenderer.draw(viewmtx, projmtx);
  117. }
  118.  
  119. // No tracking error at this point. If we detected any plane, then hide the
  120. // message UI, otherwise show searchingPlane message.
  121. if (hasTrackingPlane()) {
  122. messageSnackbarHelper.hide(this);
  123. } else {
  124. messageSnackbarHelper.showMessage(this, SEARCHING_PLANE_MESSAGE);
  125. }
  126.  
  127. // Visualize planes.
  128. planeRenderer.drawPlanes(
  129. arSession.getAllTrackables(Plane.class), camera.getDisplayOrientedPose(), projmtx);
  130.  
  131. // Visualize anchors created by touch.
  132. float scaleFactor = 1.0f;
  133. for (ColoredAnchor coloredAnchor : anchors) {
  134. if (coloredAnchor.anchor.getTrackingState() != TrackingState.TRACKING) {
  135. continue;
  136. }
  137. // Get the current pose of an Anchor in world space. The Anchor pose is updated
  138. // during calls to session.update() as ARCore refines its estimate of the world.
  139. coloredAnchor.anchor.getPose().toMatrix(anchorMatrix, 0);
  140.  
  141. // Update and draw the model and its shadow.
  142. virtualObject.updateModelMatrix(anchorMatrix, scaleFactor);
  143. //virtualObjectShadow.updateModelMatrix(anchorMatrix, scaleFactor);
  144. virtualObject.draw(viewmtx, projmtx, colorCorrectionRgba, coloredAnchor.color);
  145. //virtualObjectShadow.draw(viewmtx, projmtx, colorCorrectionRgba, coloredAnchor.color);
  146. }
  147.  
  148. } catch (Throwable t) {
  149. // Avoid crashing the application due to unhandled exceptions.
  150. Log.e(TAG, "Exception on the OpenGL thread", t);
  151. }
  152. }
  153.  
  154. // Handle only one tap per frame, as taps are usually low frequency compared to frame rate.
  155. private void handleTap(Frame frame, Camera camera) {
  156. MotionEvent tap = tapHelper.poll();
  157. if (tap != null && camera.getTrackingState() == TrackingState.TRACKING) {
  158. for (HitResult hit : frame.hitTest(tap)) {
  159. // Check if any plane was hit, and if it was hit inside the plane polygon
  160. Trackable trackable = hit.getTrackable();
  161. // Creates an anchor if a plane or an oriented point was hit.
  162. if ((trackable instanceof Plane
  163. && ((Plane) trackable).isPoseInPolygon(hit.getHitPose())
  164. && (PlaneRenderer.calculateDistanceToPlane(hit.getHitPose(), camera.getPose()) > 0))
  165. || (trackable instanceof Point
  166. && ((Point) trackable).getOrientationMode()
  167. == Point.OrientationMode.ESTIMATED_SURFACE_NORMAL)) {
  168. // Hits are sorted by depth. Consider only closest hit on a plane or oriented point.
  169. // Cap the number of objects created. This avoids overloading both the
  170. // rendering system and ARCore.
  171. if (anchors.size() >= 20) {
  172. anchors.get(0).anchor.detach();
  173. anchors.remove(0);
  174. }
  175.  
  176. // Assign a color to the object for rendering based on the trackable type
  177. // this anchor attached to. For AR_TRACKABLE_POINT, it's blue color, and
  178. // for AR_TRACKABLE_PLANE, it's green color.
  179. float[] objColor;
  180. if (trackable instanceof Point) {
  181. objColor = new float[] {66.0f, 133.0f, 244.0f, 255.0f};
  182. } else {
  183. objColor = new float[] {139.0f, 195.0f, 74.0f, 255.0f};
  184. }
  185.  
  186. // Adding an Anchor tells ARCore that it should track this position in
  187. // space. This anchor is created on the Plane to place the 3D model
  188. // in the correct position relative both to the world and to the plane.
  189. anchors.add(new ColoredAnchor(hit.createAnchor(), objColor));
  190. break;
  191. }
  192. }
  193. }
  194. }
  195.  
  196. private boolean hasTrackingPlane() {
  197. for (Plane plane : arSession.getAllTrackables(Plane.class)) {
  198. if (plane.getTrackingState() == TrackingState.TRACKING) {
  199. return true;
  200. }
  201. }
  202. return false;
  203. }
  204.  
  205. // Anchors created from taps used for object placing with a given color.
  206. private static class ColoredAnchor {
  207. final Anchor anchor;
  208. final float[] color;
  209.  
  210. ColoredAnchor(Anchor a, float[] color4f) {
  211. this.anchor = a;
  212. this.color = color4f;
  213. }
  214. }
  215.  
  216. private final ArrayList<ColoredAnchor> anchors = new ArrayList<>();
  217.  
  218. private Session arSession;
  219. private boolean RequestedInstall = true;
  220.  
  221. @SuppressLint("ClickableViewAccessibility")
  222. @Override
  223. protected void onCreate(Bundle savedInstanceState) {
  224. super.onCreate(savedInstanceState);
  225. setContentView(R.layout.activity_ar_view);
  226.  
  227. surfaceView = findViewById(R.id.surface_view);
  228. displayRotationHelper = new DRH(/*context=*/ this);
  229.  
  230. // Set up tap listener.
  231. tapHelper = new TH(/*context=*/ this);
  232. surfaceView.setOnTouchListener(tapHelper);
  233.  
  234. // Set up renderer.
  235. surfaceView.setPreserveEGLContextOnPause(true);
  236. surfaceView.setEGLContextClientVersion(2);
  237. surfaceView.setEGLConfigChooser(8, 8, 8, 8, 16, 0); // Alpha used for plane blending.
  238. surfaceView.setRenderer(this);
  239. surfaceView.setRenderMode(GLSurfaceView.RENDERMODE_CONTINUOUSLY);
  240. surfaceView.setWillNotDraw(false);
  241.  
  242. }
  243.  
  244. @Override
  245. protected void onResume() {
  246. super.onResume();
  247.  
  248. if (CPH.hasCameraPermission(this)) {
  249. CPH.requestCameraPermission(this);
  250. return;
  251. }
  252.  
  253. // Make sure Google Play Services for AR is installed and up to date.
  254. try {
  255. if (arSession == null) {
  256. switch (ArCoreApk.getInstance().requestInstall(this, RequestedInstall)) {
  257. case INSTALLED:
  258. // Success, create the AR session.
  259. arSession = new Session(this);
  260. break;
  261. case INSTALL_REQUESTED:
  262. // Ensures next invocation of requestInstall() will either return
  263. // INSTALLED or throw an exception.
  264. RequestedInstall = false;
  265. }
  266. }
  267. } catch (UnavailableUserDeclinedInstallationException e) {
  268. // Display an appropriate message to the user and return gracefully.
  269. Toast.makeText(this, "TODO: handle exception " + e, Toast.LENGTH_LONG)
  270. .show();
  271. } catch (Exception ex) {
  272. // Current catch statements.
  273. // mSession is still null.
  274. }
  275.  
  276. try {
  277. if (arSession != null) {
  278. arSession.resume();
  279. }
  280. } catch (CameraNotAvailableException e) {
  281. // In some cases (such as another camera app launching) the camera may be given to
  282. // a different app instead. Handle this properly by showing a message and recreate the
  283. // session at the next iteration.
  284. messageSnackbarHelper.showError(this, "Camera not available. Please restart the app.");
  285. arSession = null;
  286. return;
  287. }
  288.  
  289. surfaceView.onResume();
  290. displayRotationHelper.onResume();
  291. }
  292.  
  293. @Override
  294. public void onPause() {
  295. super.onPause();
  296. if (arSession != null) {
  297. // Note that the order matters - GLSurfaceView is paused first so that it does not try
  298. // to query the session. If Session is paused before GLSurfaceView, GLSurfaceView may
  299. // still call session.update() and get a SessionPausedException.
  300. displayRotationHelper.onPause();
  301. surfaceView.onPause();
  302. arSession.pause();
  303. }
  304. }
  305.  
  306. @Override
  307. public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
  308. if (CPH.hasCameraPermission(this)) {
  309. Toast.makeText(this, "Camera permission is needed to run this application", Toast.LENGTH_LONG)
  310. .show();
  311. if (!CPH.shouldShowRequestPermissionRationale(this)) {
  312. // Permission denied with checking "Do not ask again".
  313. CPH.launchPermissionSettings(this);
  314. }
  315. finish();
  316. }
  317. }
  318. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement