Index: remoting/android/java/src/org/chromium/chromoting/cardboard/CardboardRenderer.java |
diff --git a/remoting/android/java/src/org/chromium/chromoting/cardboard/CardboardRenderer.java b/remoting/android/java/src/org/chromium/chromoting/cardboard/CardboardRenderer.java |
deleted file mode 100644 |
index 72cc570b2aff5b080297384e79a2c1b7983647b1..0000000000000000000000000000000000000000 |
--- a/remoting/android/java/src/org/chromium/chromoting/cardboard/CardboardRenderer.java |
+++ /dev/null |
@@ -1,437 +0,0 @@ |
-// Copyright 2015 The Chromium Authors. All rights reserved. |
-// Use of this source code is governed by a BSD-style license that can be |
-// found in the LICENSE file. |
- |
-package org.chromium.chromoting.cardboard; |
- |
-import android.app.Activity; |
-import android.graphics.Point; |
-import android.graphics.PointF; |
-import android.opengl.GLES20; |
-import android.opengl.Matrix; |
- |
-import com.google.vrtoolkit.cardboard.CardboardView; |
-import com.google.vrtoolkit.cardboard.Eye; |
-import com.google.vrtoolkit.cardboard.HeadTransform; |
-import com.google.vrtoolkit.cardboard.Viewport; |
- |
-import org.chromium.chromoting.jni.Client; |
-import org.chromium.chromoting.jni.Display; |
- |
-import javax.microedition.khronos.egl.EGLConfig; |
- |
-/** |
- * Renderer for Cardboard view. |
- */ |
-public class CardboardRenderer implements CardboardView.StereoRenderer { |
- private static final String TAG = "cr.CardboardRenderer"; |
- |
- private static final int BYTE_PER_FLOAT = 4; |
- private static final int POSITION_DATA_SIZE = 3; |
- private static final int TEXTURE_COORDINATE_DATA_SIZE = 2; |
- private static final float Z_NEAR = 0.1f; |
- private static final float Z_FAR = 1000.0f; |
- |
- // Desktop position is fixed in world coordinates. |
- private static final float DESKTOP_POSITION_X = 0.0f; |
- private static final float DESKTOP_POSITION_Y = 0.0f; |
- private static final float DESKTOP_POSITION_Z = -2.0f; |
- |
- // Menu bar position is relative to the view point. |
- private static final float MENU_BAR_POSITION_X = 0.0f; |
- private static final float MENU_BAR_POSITION_Y = 0.0f; |
- private static final float MENU_BAR_POSITION_Z = -0.9f; |
- |
- private static final float HALF_SKYBOX_SIZE = 100.0f; |
- private static final float VIEW_POSITION_MIN = -1.0f; |
- private static final float VIEW_POSITION_MAX = 3.0f; |
- |
- // Allows user to click even when looking outside the desktop |
- // but within edge margin. |
- private static final float EDGE_MARGIN = 0.1f; |
- |
- // Distance to move camera each time. |
- private static final float CAMERA_MOTION_STEP = 0.5f; |
- |
- // This ratio is used by {@link isLookingFarawayFromDesktop()} to determine the |
- // angle beyond which the user is looking faraway from the desktop. |
- // The ratio is based on half of the desktop's angular width, as seen from |
- // the camera position. |
- // If the user triggers the button while looking faraway, this will cause the |
- // desktop to be re-positioned in the center of the view. |
- private static final float FARAWAY_ANGLE_RATIO = 1.6777f; |
- |
- // Small number used to avoid division-overflow or other problems with |
- // floating-point imprecision. |
- private static final float EPSILON = 1e-5f; |
- |
- private final Activity mActivity; |
- private final Client mClient; |
- private final Display mDisplay; |
- |
- private float mCameraPosition; |
- |
- // Lock to allow multithreaded access to mCameraPosition. |
- private final Object mCameraPositionLock = new Object(); |
- |
- private float[] mCameraMatrix; |
- private float[] mViewMatrix; |
- private float[] mProjectionMatrix; |
- |
- // Make matrix member variable to avoid unnecessary initialization. |
- private float[] mDesktopModelMatrix; |
- private float[] mDesktopCombinedMatrix; |
- private float[] mEyePointModelMatrix; |
- private float[] mEyePointCombinedMatrix; |
- private float[] mPhotosphereCombinedMatrix; |
- |
- // Direction that user is looking towards. |
- private float[] mForwardVector; |
- |
- // Eye position at the desktop distance. |
- private PointF mEyeDesktopPosition; |
- |
- // Eye position at the menu bar distance; |
- private PointF mEyeMenuBarPosition; |
- |
- private Desktop mDesktop; |
- private MenuBar mMenuBar; |
- private Photosphere mPhotosphere; |
- private Cursor mCursor; |
- |
- // Lock for eye position related operations. |
- // This protects access to mEyeDesktopPosition. |
- private final Object mEyeDesktopPositionLock = new Object(); |
- |
- // Flag to indicate whether to show menu bar. |
- private boolean mMenuBarVisible; |
- |
- public CardboardRenderer(Activity activity, Client client, Display display) { |
- mActivity = activity; |
- mClient = client; |
- mDisplay = display; |
- mCameraPosition = 0.0f; |
- |
- mCameraMatrix = new float[16]; |
- mViewMatrix = new float[16]; |
- mProjectionMatrix = new float[16]; |
- mDesktopModelMatrix = new float[16]; |
- mDesktopCombinedMatrix = new float[16]; |
- mEyePointModelMatrix = new float[16]; |
- mEyePointCombinedMatrix = new float[16]; |
- mPhotosphereCombinedMatrix = new float[16]; |
- |
- mForwardVector = new float[3]; |
- } |
- |
- private void initializeRedrawCallback() { |
- mActivity.runOnUiThread(new Runnable() { |
- public void run() { |
- mDisplay.provideRedrawCallback(new Runnable() { |
- @Override |
- public void run() { |
- mDesktop.reloadTexture(); |
- mCursor.reloadTexture(); |
- } |
- }); |
- |
- mDisplay.redrawGraphics(); |
- } |
- }); |
- } |
- |
- @Override |
- public void onSurfaceCreated(EGLConfig config) { |
- // Set the background clear color to black. |
- GLES20.glClearColor(0.0f, 0.0f, 0.0f, 0.0f); |
- |
- // Use culling to remove back faces. |
- GLES20.glEnable(GLES20.GL_CULL_FACE); |
- |
- // Enable depth testing. |
- GLES20.glEnable(GLES20.GL_DEPTH_TEST); |
- |
- mDesktop = new Desktop(mDisplay); |
- mMenuBar = new MenuBar(mActivity); |
- mPhotosphere = new Photosphere(mActivity); |
- mCursor = new Cursor(mClient, mDisplay); |
- |
- initializeRedrawCallback(); |
- } |
- |
- @Override |
- public void onSurfaceChanged(int width, int height) { |
- } |
- |
- @Override |
- public void onNewFrame(HeadTransform headTransform) { |
- // Position the eye at the origin. |
- float eyeX = 0.0f; |
- float eyeY = 0.0f; |
- float eyeZ; |
- synchronized (mCameraPositionLock) { |
- eyeZ = mCameraPosition; |
- } |
- |
- // We are looking toward the negative Z direction. |
- float lookX = DESKTOP_POSITION_X; |
- float lookY = DESKTOP_POSITION_Y; |
- float lookZ = DESKTOP_POSITION_Z; |
- |
- // Set our up vector. This is where our head would be pointing were we holding the camera. |
- float upX = 0.0f; |
- float upY = 1.0f; |
- float upZ = 0.0f; |
- |
- Matrix.setLookAtM(mCameraMatrix, 0, eyeX, eyeY, eyeZ, lookX, lookY, lookZ, upX, upY, upZ); |
- |
- headTransform.getForwardVector(mForwardVector, 0); |
- mEyeDesktopPosition = getLookingPosition(Math.abs(DESKTOP_POSITION_Z - eyeZ)); |
- mEyeMenuBarPosition = getLookingPosition(Math.abs(MENU_BAR_POSITION_Z)); |
- mDesktop.maybeLoadDesktopTexture(); |
- mPhotosphere.maybeLoadTextureAndCleanImage(); |
- mCursor.maybeLoadTexture(mDesktop); |
- mCursor.moveTo(getMouseCoordinates()); |
- } |
- |
- @Override |
- public void onDrawEye(Eye eye) { |
- GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT); |
- |
- // Apply the eye transformation to the camera. |
- Matrix.multiplyMM(mViewMatrix, 0, eye.getEyeView(), 0, mCameraMatrix, 0); |
- |
- mProjectionMatrix = eye.getPerspective(Z_NEAR, Z_FAR); |
- |
- drawDesktop(); |
- drawPhotosphere(eye.getType()); |
- drawMenuBar(); |
- drawCursor(); |
- } |
- |
- @Override |
- public void onRendererShutdown() { |
- mDesktop.cleanup(); |
- mMenuBar.cleanup(); |
- mPhotosphere.cleanup(); |
- mCursor.cleanup(); |
- } |
- |
- @Override |
- public void onFinishFrame(Viewport viewport) { |
- } |
- |
- private void drawCursor() { |
- if (!isLookingAtDesktop() || (isMenuBarVisible() && isLookingAtMenuBar()) |
- || !mCursor.hasImageFrame()) { |
- return; |
- } |
- |
- float eyePointX = clamp(mEyeDesktopPosition.x, -mDesktop.getHalfWidth(), |
- mDesktop.getHalfWidth()); |
- float eyePointY = clamp(mEyeDesktopPosition.y, -mDesktop.getHalfHeight(), |
- mDesktop.getHalfHeight()); |
- |
- Matrix.setIdentityM(mEyePointModelMatrix, 0); |
- Matrix.translateM(mEyePointModelMatrix, 0, eyePointX , eyePointY, DESKTOP_POSITION_Z); |
- |
- Matrix.multiplyMM(mEyePointCombinedMatrix, 0, mViewMatrix, 0, mEyePointModelMatrix, 0); |
- Matrix.multiplyMM(mEyePointCombinedMatrix, 0, mProjectionMatrix, |
- 0, mEyePointCombinedMatrix, 0); |
- |
- mCursor.draw(mEyePointCombinedMatrix); |
- } |
- |
- private void drawPhotosphere(int eyeType) { |
- // Since we will always put the photosphere center in the origin, the |
- // model matrix will always be identity matrix which we can ignore. |
- Matrix.multiplyMM(mPhotosphereCombinedMatrix, 0, mProjectionMatrix, |
- 0, mViewMatrix, 0); |
- |
- mPhotosphere.draw(mPhotosphereCombinedMatrix, eyeType); |
- } |
- |
- private void drawDesktop() { |
- if (!mDesktop.hasVideoFrame()) { |
- // This can happen if the client is connected, but a complete |
- // video frame has not yet been decoded. |
- return; |
- } |
- |
- Matrix.setIdentityM(mDesktopModelMatrix, 0); |
- Matrix.translateM(mDesktopModelMatrix, 0, DESKTOP_POSITION_X, |
- DESKTOP_POSITION_Y, DESKTOP_POSITION_Z); |
- |
- // Pass in Model View Matrix and Model View Project Matrix. |
- Matrix.multiplyMM(mDesktopCombinedMatrix, 0, mViewMatrix, 0, mDesktopModelMatrix, 0); |
- Matrix.multiplyMM(mDesktopCombinedMatrix, 0, mProjectionMatrix, |
- 0, mDesktopCombinedMatrix, 0); |
- |
- mDesktop.draw(mDesktopCombinedMatrix, mMenuBarVisible); |
- } |
- |
- private void drawMenuBar() { |
- if (!mMenuBarVisible) { |
- return; |
- } |
- |
- float menuBarZ; |
- synchronized (mCameraPositionLock) { |
- menuBarZ = mCameraPosition + MENU_BAR_POSITION_Z; |
- } |
- |
- |
- mMenuBar.draw(mViewMatrix, mProjectionMatrix, mEyeMenuBarPosition, MENU_BAR_POSITION_X, |
- MENU_BAR_POSITION_Y, menuBarZ); |
- } |
- |
- /** |
- * Return menu item that is currently looking at or null if not looking at menu bar. |
- */ |
- public MenuItem getMenuItem() { |
- // Transform world view to model view. |
- return mMenuBar.getLookingItem(new PointF(mEyeMenuBarPosition.x - MENU_BAR_POSITION_X, |
- mEyeMenuBarPosition.y - MENU_BAR_POSITION_Y)); |
- } |
- |
- /** |
- * Returns coordinates in units of pixels in the desktop bitmap. |
- * This can be called on any thread. |
- */ |
- public PointF getMouseCoordinates() { |
- PointF result = new PointF(); |
- Point shapePixels = mDesktop.getFrameSizePixels(); |
- int widthPixels = shapePixels.x; |
- int heightPixels = shapePixels.y; |
- |
- synchronized (mEyeDesktopPositionLock) { |
- // Due to the coordinate direction, we only have to inverse x. |
- result.x = (mEyeDesktopPosition.x + mDesktop.getHalfWidth()) |
- / (2 * mDesktop.getHalfWidth()) * widthPixels; |
- result.y = (-mEyeDesktopPosition.y + mDesktop.getHalfHeight()) |
- / (2 * mDesktop.getHalfHeight()) * heightPixels; |
- result.x = clamp(result.x, 0, widthPixels); |
- result.y = clamp(result.y, 0, heightPixels); |
- } |
- return result; |
- } |
- |
- /** |
- * Returns the passed in value if it resides within the specified range (inclusive). If not, |
- * it will return the closest boundary from the range. The ordering of the boundary values |
- * does not matter. |
- * |
- * @param value The value to be compared against the range. |
- * @param a First boundary range value. |
- * @param b Second boundary range value. |
- * @return The passed in value if it is within the range, otherwise the closest boundary value. |
- */ |
- private static float clamp(float value, float a, float b) { |
- float min = (a > b) ? b : a; |
- float max = (a > b) ? a : b; |
- if (value < min) { |
- value = min; |
- } else if (value > max) { |
- value = max; |
- } |
- return value; |
- } |
- |
- /** |
- * Move the camera towards desktop. |
- * This method can be called on any thread. |
- */ |
- public void moveTowardsDesktop() { |
- synchronized (mCameraPositionLock) { |
- float newPosition = mCameraPosition - CAMERA_MOTION_STEP; |
- if (newPosition >= VIEW_POSITION_MIN) { |
- mCameraPosition = newPosition; |
- } |
- } |
- } |
- |
- /** |
- * Move the camera away from desktop. |
- * This method can be called on any thread. |
- */ |
- public void moveAwayFromDesktop() { |
- synchronized (mCameraPositionLock) { |
- float newPosition = mCameraPosition + CAMERA_MOTION_STEP; |
- if (newPosition <= VIEW_POSITION_MAX) { |
- mCameraPosition = newPosition; |
- } |
- } |
- } |
- |
- /** |
- * Return true if user is looking at the desktop. |
- * This method can be called on any thread. |
- */ |
- public boolean isLookingAtDesktop() { |
- synchronized (mEyeDesktopPositionLock) { |
- // TODO(shichengfeng): Move logic to CardboardActivityDesktop. |
- return mForwardVector[2] < 0 |
- && Math.abs(mEyeDesktopPosition.x) <= (mDesktop.getHalfWidth() + EDGE_MARGIN) |
- && Math.abs(mEyeDesktopPosition.y) <= (mDesktop.getHalfHeight() + EDGE_MARGIN); |
- } |
- } |
- |
- /** |
- * Return true if user is looking at the menu bar. |
- */ |
- public boolean isLookingAtMenuBar() { |
- return mForwardVector[2] < 0 |
- && mMenuBar.contains(new PointF(mEyeMenuBarPosition.x - MENU_BAR_POSITION_X, |
- mEyeMenuBarPosition.y - MENU_BAR_POSITION_Y)); |
- } |
- |
- /** |
- * Get eye position at the given distance. |
- */ |
- private PointF getLookingPosition(float distance) { |
- if (Math.abs(mForwardVector[2]) < EPSILON) { |
- return new PointF(Math.copySign(Float.MAX_VALUE, mForwardVector[0]), |
- Math.copySign(Float.MAX_VALUE, mForwardVector[1])); |
- } else { |
- return new PointF(mForwardVector[0] * distance / mForwardVector[2], |
- mForwardVector[1] * distance / mForwardVector[2]); |
- } |
- } |
- |
- /** |
- * Set the visibility of the menu bar. |
- */ |
- public void setMenuBarVisible(boolean visible) { |
- mMenuBarVisible = visible; |
- } |
- |
- /** |
- * Return true if menu bar is visible. |
- */ |
- public boolean isMenuBarVisible() { |
- return mMenuBarVisible; |
- } |
- |
- |
- /** |
- * Return true if user is looking faraway from desktop. |
- */ |
- public boolean isLookingFarawayFromDesktop() { |
- if (mForwardVector[2] > -EPSILON) { |
- // If user is looking towards the back. |
- return true; |
- } |
- |
- // Calculate half desktop looking angle. |
- double theta; |
- synchronized (mCameraPositionLock) { |
- theta = Math.atan(mDesktop.getHalfWidth() |
- / (DESKTOP_POSITION_Z - mCameraPosition)); |
- } |
- |
- // Calculate current looking angle. |
- double phi = Math.atan(mForwardVector[0] / mForwardVector[2]); |
- |
- return Math.abs(phi) > FARAWAY_ANGLE_RATIO * Math.abs(theta); |
- } |
-} |