| OLD | NEW |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 package org.chromium.chromoting; | 5 package org.chromium.chromoting; |
| 6 | 6 |
| 7 import android.app.Activity; | 7 import android.app.Activity; |
| 8 import android.graphics.Bitmap; | 8 import android.graphics.Bitmap; |
| 9 import android.graphics.BitmapFactory; | 9 import android.graphics.BitmapFactory; |
| 10 import android.graphics.Point; |
| 10 import android.graphics.PointF; | 11 import android.graphics.PointF; |
| 11 import android.opengl.GLES20; | 12 import android.opengl.GLES20; |
| 12 import android.opengl.Matrix; | 13 import android.opengl.Matrix; |
| 13 | 14 |
| 14 import com.google.vrtoolkit.cardboard.CardboardView; | 15 import com.google.vrtoolkit.cardboard.CardboardView; |
| 15 import com.google.vrtoolkit.cardboard.Eye; | 16 import com.google.vrtoolkit.cardboard.Eye; |
| 16 import com.google.vrtoolkit.cardboard.HeadTransform; | 17 import com.google.vrtoolkit.cardboard.HeadTransform; |
| 17 import com.google.vrtoolkit.cardboard.Viewport; | 18 import com.google.vrtoolkit.cardboard.Viewport; |
| 18 | 19 |
| 19 import org.chromium.base.Log; | 20 import org.chromium.base.Log; |
| (...skipping 20 matching lines...) Expand all Loading... |
| 40 private static final float DESKTOP_POSITION_Y = 0.0f; | 41 private static final float DESKTOP_POSITION_Y = 0.0f; |
| 41 private static final float DESKTOP_POSITION_Z = -2.0f; | 42 private static final float DESKTOP_POSITION_Z = -2.0f; |
| 42 private static final float HALF_SKYBOX_SIZE = 100.0f; | 43 private static final float HALF_SKYBOX_SIZE = 100.0f; |
| 43 private static final float VIEW_POSITION_MIN = -1.0f; | 44 private static final float VIEW_POSITION_MIN = -1.0f; |
| 44 private static final float VIEW_POSITION_MAX = 3.0f; | 45 private static final float VIEW_POSITION_MAX = 3.0f; |
| 45 | 46 |
| 46 // Allows user to click even when looking outside the desktop | 47 // Allows user to click even when looking outside the desktop |
| 47 // but within edge margin. | 48 // but within edge margin. |
| 48 private static final float EDGE_MARGIN = 0.1f; | 49 private static final float EDGE_MARGIN = 0.1f; |
| 49 | 50 |
| 50 // Fix the desktop height and adjust width accordingly. | |
| 51 private static final float HALF_DESKTOP_HEIGHT = 1.0f; | |
| 52 | |
| 53 // Distance to move camera each time. | 51 // Distance to move camera each time. |
| 54 private static final float CAMERA_MOTION_STEP = 0.5f; | 52 private static final float CAMERA_MOTION_STEP = 0.5f; |
| 55 | 53 |
| 56 private static final FloatBuffer DESKTOP_TEXTURE_COORDINATES = makeFloatBuff
er(new float[] { | |
| 57 // Texture coordinate data. | |
| 58 0.0f, 0.0f, | |
| 59 0.0f, 1.0f, | |
| 60 1.0f, 0.0f, | |
| 61 0.0f, 1.0f, | |
| 62 1.0f, 1.0f, | |
| 63 1.0f, 0.0f | |
| 64 }); | |
| 65 | |
| 66 private static final FloatBuffer SKYBOX_POSITION_COORDINATES = makeFloatBuff
er(new float[] { | 54 private static final FloatBuffer SKYBOX_POSITION_COORDINATES = makeFloatBuff
er(new float[] { |
| 67 -HALF_SKYBOX_SIZE, HALF_SKYBOX_SIZE, HALF_SKYBOX_SIZE, // (0) Top
-left near | 55 -HALF_SKYBOX_SIZE, HALF_SKYBOX_SIZE, HALF_SKYBOX_SIZE, // (0) Top
-left near |
| 68 HALF_SKYBOX_SIZE, HALF_SKYBOX_SIZE, HALF_SKYBOX_SIZE, // (1) Top-
right near | 56 HALF_SKYBOX_SIZE, HALF_SKYBOX_SIZE, HALF_SKYBOX_SIZE, // (1) Top-
right near |
| 69 -HALF_SKYBOX_SIZE, -HALF_SKYBOX_SIZE, HALF_SKYBOX_SIZE, // (2) Bot
tom-left near | 57 -HALF_SKYBOX_SIZE, -HALF_SKYBOX_SIZE, HALF_SKYBOX_SIZE, // (2) Bot
tom-left near |
| 70 HALF_SKYBOX_SIZE, -HALF_SKYBOX_SIZE, HALF_SKYBOX_SIZE, // (3) Bott
om-right near | 58 HALF_SKYBOX_SIZE, -HALF_SKYBOX_SIZE, HALF_SKYBOX_SIZE, // (3) Bott
om-right near |
| 71 -HALF_SKYBOX_SIZE, HALF_SKYBOX_SIZE, -HALF_SKYBOX_SIZE, // (4) Top
-left far | 59 -HALF_SKYBOX_SIZE, HALF_SKYBOX_SIZE, -HALF_SKYBOX_SIZE, // (4) Top
-left far |
| 72 HALF_SKYBOX_SIZE, HALF_SKYBOX_SIZE, -HALF_SKYBOX_SIZE, // (5) Top-
right far | 60 HALF_SKYBOX_SIZE, HALF_SKYBOX_SIZE, -HALF_SKYBOX_SIZE, // (5) Top-
right far |
| 73 -HALF_SKYBOX_SIZE, -HALF_SKYBOX_SIZE, -HALF_SKYBOX_SIZE, // (6) Bot
tom-left far | 61 -HALF_SKYBOX_SIZE, -HALF_SKYBOX_SIZE, -HALF_SKYBOX_SIZE, // (6) Bot
tom-left far |
| 74 HALF_SKYBOX_SIZE, -HALF_SKYBOX_SIZE, -HALF_SKYBOX_SIZE // (7) Botto
m-right far | 62 HALF_SKYBOX_SIZE, -HALF_SKYBOX_SIZE, -HALF_SKYBOX_SIZE // (7) Botto
m-right far |
| 75 }); | 63 }); |
| (...skipping 17 matching lines...) Expand all Loading... |
| 93 | 81 |
| 94 // Top | 82 // Top |
| 95 5, 1, 4, | 83 5, 1, 4, |
| 96 4, 1, 0, | 84 4, 1, 0, |
| 97 | 85 |
| 98 // Bottom | 86 // Bottom |
| 99 6, 2, 7, | 87 6, 2, 7, |
| 100 7, 2, 3 | 88 7, 2, 3 |
| 101 }); | 89 }); |
| 102 | 90 |
| 103 private static final String DESKTOP_VERTEX_SHADER = | |
| 104 "uniform mat4 u_CombinedMatrix;" | |
| 105 + "attribute vec4 a_Position;" | |
| 106 + "attribute vec2 a_TexCoordinate;" | |
| 107 + "varying vec2 v_TexCoordinate;" | |
| 108 + "void main() {" | |
| 109 + " v_TexCoordinate = a_TexCoordinate;" | |
| 110 + " gl_Position = u_CombinedMatrix * a_Position;" | |
| 111 + "}"; | |
| 112 | |
| 113 private static final String DESKTOP_FRAGMENT_SHADER = | |
| 114 "precision highp float;" | |
| 115 + "uniform sampler2D u_Texture;" | |
| 116 + "varying vec2 v_TexCoordinate;" | |
| 117 + "const float borderWidth = 0.002;" | |
| 118 + "void main() {" | |
| 119 + " if (v_TexCoordinate.x > (1.0 - borderWidth) || v_TexCoordinate.
x < borderWidth" | |
| 120 + " || v_TexCoordinate.y > (1.0 - borderWidth)" | |
| 121 + " || v_TexCoordinate.y < borderWidth) {" | |
| 122 + " gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);" | |
| 123 + " } else {" | |
| 124 + " gl_FragColor = texture2D(u_Texture, v_TexCoordinate);" | |
| 125 + " }" | |
| 126 + "}"; | |
| 127 | |
| 128 private static final String SKYBOX_VERTEX_SHADER = | 91 private static final String SKYBOX_VERTEX_SHADER = |
| 129 "uniform mat4 u_CombinedMatrix;" | 92 "uniform mat4 u_CombinedMatrix;" |
| 130 + "attribute vec3 a_Position;" | 93 + "attribute vec3 a_Position;" |
| 131 + "varying vec3 v_Position;" | 94 + "varying vec3 v_Position;" |
| 132 + "void main() {" | 95 + "void main() {" |
| 133 + " v_Position = a_Position;" | 96 + " v_Position = a_Position;" |
| 134 // Make sure to convert from the right-handed coordinate system of t
he | 97 // Make sure to convert from the right-handed coordinate system of t
he |
| 135 // world to the left-handed coordinate system of the cube map, other
wise, | 98 // world to the left-handed coordinate system of the cube map, other
wise, |
| 136 // our cube map will still work but everything will be flipped. | 99 // our cube map will still work but everything will be flipped. |
| 137 + " v_Position.z = -v_Position.z;" | 100 + " v_Position.z = -v_Position.z;" |
| (...skipping 20 matching lines...) Expand all Loading... |
| 158 "https://dl.google.com/chrome-remote-desktop/android-assets/room_back.pn
g", | 121 "https://dl.google.com/chrome-remote-desktop/android-assets/room_back.pn
g", |
| 159 "https://dl.google.com/chrome-remote-desktop/android-assets/room_front.p
ng" | 122 "https://dl.google.com/chrome-remote-desktop/android-assets/room_front.p
ng" |
| 160 }; | 123 }; |
| 161 | 124 |
| 162 private static final String[] SKYBOX_IMAGE_NAMES = new String[] { | 125 private static final String[] SKYBOX_IMAGE_NAMES = new String[] { |
| 163 "skybox_left", "skybox_right", "skybox_bottom", "skybox_top", "skybox_ba
ck", "skybox_front" | 126 "skybox_left", "skybox_right", "skybox_bottom", "skybox_top", "skybox_ba
ck", "skybox_front" |
| 164 }; | 127 }; |
| 165 | 128 |
| 166 private final Activity mActivity; | 129 private final Activity mActivity; |
| 167 | 130 |
| 168 private float mHalfDesktopWidth; | |
| 169 private float mCameraPosition; | 131 private float mCameraPosition; |
| 170 | 132 |
| 171 // Lock to allow multithreaded access to mCameraPosition. | 133 // Lock to allow multithreaded access to mCameraPosition. |
| 172 private Object mCameraPositionLock = new Object(); | 134 private Object mCameraPositionLock = new Object(); |
| 173 | 135 |
| 174 private float[] mCameraMatrix; | 136 private float[] mCameraMatrix; |
| 175 private float[] mViewMatrix; | 137 private float[] mViewMatrix; |
| 176 private float[] mProjectionMatrix; | 138 private float[] mProjectionMatrix; |
| 177 | 139 |
| 178 // Make matrix member variable to avoid unnecessary initialization. | 140 // Make matrix member variable to avoid unnecessary initialization. |
| 179 private float[] mDesktopModelMatrix; | 141 private float[] mDesktopModelMatrix; |
| 180 private float[] mDesktopCombinedMatrix; | 142 private float[] mDesktopCombinedMatrix; |
| 181 private float[] mEyePointModelMatrix; | 143 private float[] mEyePointModelMatrix; |
| 182 private float[] mEyePointCombinedMatrix; | 144 private float[] mEyePointCombinedMatrix; |
| 183 private float[] mSkyboxModelMatrix; | 145 private float[] mSkyboxModelMatrix; |
| 184 private float[] mSkyboxCombinedMatrix; | 146 private float[] mSkyboxCombinedMatrix; |
| 185 | 147 |
| 186 // Direction that user is looking towards. | 148 // Direction that user is looking towards. |
| 187 private float[] mForwardVector; | 149 private float[] mForwardVector; |
| 188 | 150 |
| 189 // Eye position in desktop. | 151 // Eye position in desktop. |
| 190 private float[] mEyePositionVector; | 152 private float[] mEyePositionVector; |
| 191 | 153 |
| 192 private int mDesktopCombinedMatrixHandle; | |
| 193 private int mPositionHandle; | |
| 194 private int mTextureDataHandle; | |
| 195 private int mTextureUniformHandle; | |
| 196 private int mTextureCoordinateHandle; | |
| 197 private int mProgramHandle; | |
| 198 private int mDesktopVertexShaderHandle; | |
| 199 private int mDesktopFragmentShaderHandle; | |
| 200 private int mSkyboxVertexShaderHandle; | 154 private int mSkyboxVertexShaderHandle; |
| 201 private int mSkyboxFragmentShaderHandle; | 155 private int mSkyboxFragmentShaderHandle; |
| 202 private int mSkyboxProgramHandle; | 156 private int mSkyboxProgramHandle; |
| 203 private int mSkyboxPositionHandle; | 157 private int mSkyboxPositionHandle; |
| 204 private int mSkyboxCombinedMatrixHandle; | 158 private int mSkyboxCombinedMatrixHandle; |
| 205 private int mSkyboxTextureUnitHandle; | 159 private int mSkyboxTextureUnitHandle; |
| 206 private int mSkyboxTextureDataHandle; | 160 private int mSkyboxTextureDataHandle; |
| 161 private CardboardActivityDesktop mDesktop; |
| 207 private CardboardActivityEyePoint mEyePoint; | 162 private CardboardActivityEyePoint mEyePoint; |
| 208 | 163 |
| 209 // Flag to indicate whether reload the desktop texture or not. | 164 // Flag to indicate whether reload the desktop texture or not. |
| 210 private boolean mReloadTexture; | 165 private boolean mReloadTexture; |
| 211 | 166 |
| 212 /** Lock to allow multithreaded access to mReloadTexture. */ | 167 /** Lock to allow multithreaded access to mReloadTexture. */ |
| 213 private Object mReloadTextureLock = new Object(); | 168 private Object mReloadTextureLock = new Object(); |
| 214 | 169 |
| 215 // Lock for eye position related operations. | 170 // Lock for eye position related operations. |
| 216 // This protects access to mEyePositionVector as well as mDesktop{Height/Wid
th}Pixels. | 171 // This protects access to mEyePositionVector. |
| 217 private Object mEyePositionLock = new Object(); | 172 private Object mEyePositionLock = new Object(); |
| 218 | 173 |
| 219 private int mDesktopHeightPixels; | |
| 220 private int mDesktopWidthPixels; | |
| 221 | |
| 222 private FloatBuffer mDesktopCoordinates; | |
| 223 | |
| 224 // Flag to signal that the skybox images are fully decoded and should be loa
ded | 174 // Flag to signal that the skybox images are fully decoded and should be loa
ded |
| 225 // into the OpenGL textures. | 175 // into the OpenGL textures. |
| 226 private boolean mLoadSkyboxImagesTexture; | 176 private boolean mLoadSkyboxImagesTexture; |
| 227 | 177 |
| 228 // Lock to allow multithreaded access to mLoadSkyboxImagesTexture. | 178 // Lock to allow multithreaded access to mLoadSkyboxImagesTexture. |
| 229 private Object mLoadSkyboxImagesTextureLock = new Object(); | 179 private Object mLoadSkyboxImagesTextureLock = new Object(); |
| 230 | 180 |
| 231 private ChromotingDownloadManager mDownloadManager; | 181 private ChromotingDownloadManager mDownloadManager; |
| 232 | 182 |
| 233 public CardboardDesktopRenderer(Activity activity) { | 183 public CardboardDesktopRenderer(Activity activity) { |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 278 public void onSurfaceCreated(EGLConfig config) { | 228 public void onSurfaceCreated(EGLConfig config) { |
| 279 // Set the background clear color to black. | 229 // Set the background clear color to black. |
| 280 GLES20.glClearColor(0.0f, 0.0f, 0.0f, 0.0f); | 230 GLES20.glClearColor(0.0f, 0.0f, 0.0f, 0.0f); |
| 281 | 231 |
| 282 // Use culling to remove back faces. | 232 // Use culling to remove back faces. |
| 283 GLES20.glEnable(GLES20.GL_CULL_FACE); | 233 GLES20.glEnable(GLES20.GL_CULL_FACE); |
| 284 | 234 |
| 285 // Enable depth testing. | 235 // Enable depth testing. |
| 286 GLES20.glEnable(GLES20.GL_DEPTH_TEST); | 236 GLES20.glEnable(GLES20.GL_DEPTH_TEST); |
| 287 | 237 |
| 288 // Set handles for desktop drawing. | |
| 289 mDesktopVertexShaderHandle = | |
| 290 ShaderHelper.compileShader(GLES20.GL_VERTEX_SHADER, DESKTOP_VERT
EX_SHADER); | |
| 291 mDesktopFragmentShaderHandle = | |
| 292 ShaderHelper.compileShader(GLES20.GL_FRAGMENT_SHADER, DESKTOP_FR
AGMENT_SHADER); | |
| 293 mProgramHandle = ShaderHelper.createAndLinkProgram(mDesktopVertexShaderH
andle, | |
| 294 mDesktopFragmentShaderHandle, new String[] {"a_Position", "a_Tex
Coordinate"}); | |
| 295 mDesktopCombinedMatrixHandle = | |
| 296 GLES20.glGetUniformLocation(mProgramHandle, "u_CombinedMatrix"); | |
| 297 mTextureUniformHandle = GLES20.glGetUniformLocation(mProgramHandle, "u_T
exture"); | |
| 298 mPositionHandle = GLES20.glGetAttribLocation(mProgramHandle, "a_Position
"); | |
| 299 mTextureCoordinateHandle = GLES20.glGetAttribLocation(mProgramHandle, "a
_TexCoordinate"); | |
| 300 mTextureDataHandle = TextureHelper.createTextureHandle(); | |
| 301 | |
| 302 // Set handlers for skybox drawing. | 238 // Set handlers for skybox drawing. |
| 303 GLES20.glEnable(GLES20.GL_TEXTURE_CUBE_MAP); | 239 GLES20.glEnable(GLES20.GL_TEXTURE_CUBE_MAP); |
| 304 mSkyboxVertexShaderHandle = | 240 mSkyboxVertexShaderHandle = |
| 305 ShaderHelper.compileShader(GLES20.GL_VERTEX_SHADER, SKYBOX_VERTE
X_SHADER); | 241 ShaderHelper.compileShader(GLES20.GL_VERTEX_SHADER, SKYBOX_VERTE
X_SHADER); |
| 306 mSkyboxFragmentShaderHandle = | 242 mSkyboxFragmentShaderHandle = |
| 307 ShaderHelper.compileShader(GLES20.GL_FRAGMENT_SHADER, SKYBOX_FRA
GMENT_SHADER); | 243 ShaderHelper.compileShader(GLES20.GL_FRAGMENT_SHADER, SKYBOX_FRA
GMENT_SHADER); |
| 308 mSkyboxProgramHandle = ShaderHelper.createAndLinkProgram(mSkyboxVertexSh
aderHandle, | 244 mSkyboxProgramHandle = ShaderHelper.createAndLinkProgram(mSkyboxVertexSh
aderHandle, |
| 309 mSkyboxFragmentShaderHandle, | 245 mSkyboxFragmentShaderHandle, |
| 310 new String[] {"a_Position", "u_CombinedMatrix", "u_TextureUnit"}
); | 246 new String[] {"a_Position", "u_CombinedMatrix", "u_TextureUnit"}
); |
| 311 mSkyboxPositionHandle = | 247 mSkyboxPositionHandle = |
| 312 GLES20.glGetAttribLocation(mSkyboxProgramHandle, "a_Position"); | 248 GLES20.glGetAttribLocation(mSkyboxProgramHandle, "a_Position"); |
| 313 mSkyboxCombinedMatrixHandle = | 249 mSkyboxCombinedMatrixHandle = |
| 314 GLES20.glGetUniformLocation(mSkyboxProgramHandle, "u_CombinedMat
rix"); | 250 GLES20.glGetUniformLocation(mSkyboxProgramHandle, "u_CombinedMat
rix"); |
| 315 mSkyboxTextureUnitHandle = | 251 mSkyboxTextureUnitHandle = |
| 316 GLES20.glGetUniformLocation(mSkyboxProgramHandle, "u_TextureUnit
"); | 252 GLES20.glGetUniformLocation(mSkyboxProgramHandle, "u_TextureUnit
"); |
| 317 mSkyboxTextureDataHandle = TextureHelper.createTextureHandle(); | 253 mSkyboxTextureDataHandle = TextureHelper.createTextureHandle(); |
| 318 | 254 |
| 255 mDesktop = new CardboardActivityDesktop(); |
| 319 mEyePoint = new CardboardActivityEyePoint(); | 256 mEyePoint = new CardboardActivityEyePoint(); |
| 320 } | 257 } |
| 321 | 258 |
| 322 @Override | 259 @Override |
| 323 public void onSurfaceChanged(int width, int height) { | 260 public void onSurfaceChanged(int width, int height) { |
| 324 } | 261 } |
| 325 | 262 |
| 326 @Override | 263 @Override |
| 327 public void onNewFrame(HeadTransform headTransform) { | 264 public void onNewFrame(HeadTransform headTransform) { |
| 328 // Position the eye at the origin. | 265 // Position the eye at the origin. |
| (...skipping 11 matching lines...) Expand all Loading... |
| 340 | 277 |
| 341 // Set our up vector. This is where our head would be pointing were we h
olding the camera. | 278 // Set our up vector. This is where our head would be pointing were we h
olding the camera. |
| 342 float upX = 0.0f; | 279 float upX = 0.0f; |
| 343 float upY = 1.0f; | 280 float upY = 1.0f; |
| 344 float upZ = 0.0f; | 281 float upZ = 0.0f; |
| 345 | 282 |
| 346 Matrix.setLookAtM(mCameraMatrix, 0, eyeX, eyeY, eyeZ, lookX, lookY, look
Z, upX, upY, upZ); | 283 Matrix.setLookAtM(mCameraMatrix, 0, eyeX, eyeY, eyeZ, lookX, lookY, look
Z, upX, upY, upZ); |
| 347 | 284 |
| 348 headTransform.getForwardVector(mForwardVector, 0); | 285 headTransform.getForwardVector(mForwardVector, 0); |
| 349 getLookingPosition(); | 286 getLookingPosition(); |
| 350 maybeLoadTexture(mTextureDataHandle); | 287 maybeLoadDesktopTexture(); |
| 351 maybeLoadCubeMapAndCleanImages(mSkyboxTextureDataHandle); | 288 maybeLoadCubeMapAndCleanImages(mSkyboxTextureDataHandle); |
| 352 } | 289 } |
| 353 | 290 |
| 354 @Override | 291 @Override |
| 355 public void onDrawEye(Eye eye) { | 292 public void onDrawEye(Eye eye) { |
| 356 GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT); | 293 GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT); |
| 357 | 294 |
| 358 // Apply the eye transformation to the camera. | 295 // Apply the eye transformation to the camera. |
| 359 Matrix.multiplyMM(mViewMatrix, 0, eye.getEyeView(), 0, mCameraMatrix, 0)
; | 296 Matrix.multiplyMM(mViewMatrix, 0, eye.getEyeView(), 0, mCameraMatrix, 0)
; |
| 360 | 297 |
| 361 mProjectionMatrix = eye.getPerspective(Z_NEAR, Z_FAR); | 298 mProjectionMatrix = eye.getPerspective(Z_NEAR, Z_FAR); |
| 362 | 299 |
| 363 drawSkybox(); | 300 drawSkybox(); |
| 364 drawDesktop(); | 301 drawDesktop(); |
| 365 drawEyePoint(); | 302 drawEyePoint(); |
| 366 } | 303 } |
| 367 | 304 |
| 368 @Override | 305 @Override |
| 369 public void onRendererShutdown() { | 306 public void onRendererShutdown() { |
| 370 GLES20.glDeleteShader(mDesktopVertexShaderHandle); | 307 mDesktop.cleanup(); |
| 371 GLES20.glDeleteShader(mDesktopFragmentShaderHandle); | |
| 372 mEyePoint.cleanup(); | 308 mEyePoint.cleanup(); |
| 373 GLES20.glDeleteShader(mSkyboxVertexShaderHandle); | 309 GLES20.glDeleteShader(mSkyboxVertexShaderHandle); |
| 374 GLES20.glDeleteShader(mSkyboxFragmentShaderHandle); | 310 GLES20.glDeleteShader(mSkyboxFragmentShaderHandle); |
| 375 GLES20.glDeleteTextures(1, new int[] {mTextureDataHandle}, 0); | |
| 376 GLES20.glDeleteTextures(1, new int[] {mSkyboxTextureDataHandle}, 0); | 311 GLES20.glDeleteTextures(1, new int[] {mSkyboxTextureDataHandle}, 0); |
| 377 mActivity.runOnUiThread(new Runnable() { | 312 mActivity.runOnUiThread(new Runnable() { |
| 378 public void run() { | 313 public void run() { |
| 379 mDownloadManager.close(); | 314 mDownloadManager.close(); |
| 380 } | 315 } |
| 381 }); | 316 }); |
| 382 } | 317 } |
| 383 | 318 |
| 384 @Override | 319 @Override |
| 385 public void onFinishFrame(Viewport viewport) { | 320 public void onFinishFrame(Viewport viewport) { |
| 386 } | 321 } |
| 387 | 322 |
| 388 private void drawDesktop() { | 323 private void drawDesktop() { |
| 389 GLES20.glUseProgram(mProgramHandle); | 324 if (!mDesktop.hasVideoFrame()) { |
| 325 // This can happen if the client is connected, but a complete |
| 326 // video frame has not yet been decoded. |
| 327 return; |
| 328 } |
| 390 | 329 |
| 391 // Translate the desktop model. | 330 |
| 392 Matrix.setIdentityM(mDesktopModelMatrix, 0); | 331 Matrix.setIdentityM(mDesktopModelMatrix, 0); |
| 393 Matrix.translateM(mDesktopModelMatrix, 0, DESKTOP_POSITION_X, | 332 Matrix.translateM(mDesktopModelMatrix, 0, DESKTOP_POSITION_X, |
| 394 DESKTOP_POSITION_Y, DESKTOP_POSITION_Z); | 333 DESKTOP_POSITION_Y, DESKTOP_POSITION_Z); |
| 395 | 334 |
| 396 // Pass in Model View Matrix and Model View Project Matrix. | 335 // Pass in Model View Matrix and Model View Project Matrix. |
| 397 Matrix.multiplyMM(mDesktopCombinedMatrix, 0, mViewMatrix, 0, mDesktopMod
elMatrix, 0); | 336 Matrix.multiplyMM(mDesktopCombinedMatrix, 0, mViewMatrix, 0, mDesktopMod
elMatrix, 0); |
| 398 Matrix.multiplyMM(mDesktopCombinedMatrix, 0, mProjectionMatrix, | 337 Matrix.multiplyMM(mDesktopCombinedMatrix, 0, mProjectionMatrix, |
| 399 0, mDesktopCombinedMatrix, 0); | 338 0, mDesktopCombinedMatrix, 0); |
| 339 mDesktop.setCombinedMatrix(mDesktopCombinedMatrix); |
| 400 | 340 |
| 401 // Pass in model view project matrix. | 341 mDesktop.draw(); |
| 402 GLES20.glUniformMatrix4fv(mDesktopCombinedMatrixHandle, 1, false, | |
| 403 mDesktopCombinedMatrix, 0); | |
| 404 | |
| 405 if (mDesktopCoordinates == null) { | |
| 406 // This can happen if the client is connected, but a complete video
frame has not yet | |
| 407 // been decoded. | |
| 408 return; | |
| 409 } | |
| 410 // Pass in the desktop position. | |
| 411 GLES20.glVertexAttribPointer(mPositionHandle, POSITION_DATA_SIZE, GLES20
.GL_FLOAT, false, | |
| 412 0, mDesktopCoordinates); | |
| 413 GLES20.glEnableVertexAttribArray(mPositionHandle); | |
| 414 | |
| 415 // Pass in texture coordinate. | |
| 416 GLES20.glVertexAttribPointer(mTextureCoordinateHandle, TEXTURE_COORDINAT
E_DATA_SIZE, | |
| 417 GLES20.GL_FLOAT, false, 0, DESKTOP_TEXTURE_COORDINATES); | |
| 418 GLES20.glEnableVertexAttribArray(mTextureCoordinateHandle); | |
| 419 | |
| 420 // Pass in texture data. | |
| 421 GLES20.glActiveTexture(GLES20.GL_TEXTURE0); | |
| 422 GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTextureDataHandle); | |
| 423 GLES20.glUniform1i(mTextureUniformHandle, 0); | |
| 424 | |
| 425 // Draw the desktop. | |
| 426 int totalPointNumber = 6; | |
| 427 GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, totalPointNumber); | |
| 428 } | 342 } |
| 429 | 343 |
| 430 private void drawEyePoint() { | 344 private void drawEyePoint() { |
| 431 if (!isLookingAtDesktop()) { | 345 if (!isLookingAtDesktop()) { |
| 432 return; | 346 return; |
| 433 } | 347 } |
| 434 | 348 |
| 435 float eyePointX = clamp(mEyePositionVector[0], -mHalfDesktopWidth, | 349 float eyePointX = clamp(mEyePositionVector[0], -mDesktop.getHalfWidth(), |
| 436 mHalfDesktopWidth); | 350 mDesktop.getHalfWidth()); |
| 437 float eyePointY = clamp(mEyePositionVector[1], -HALF_DESKTOP_HEIGHT, | 351 float eyePointY = clamp(mEyePositionVector[1], -mDesktop.getHalfHeight()
, |
| 438 HALF_DESKTOP_HEIGHT); | 352 mDesktop.getHalfHeight()); |
| 439 Matrix.setIdentityM(mEyePointModelMatrix, 0); | 353 Matrix.setIdentityM(mEyePointModelMatrix, 0); |
| 440 Matrix.translateM(mEyePointModelMatrix, 0, -eyePointX, -eyePointY, | 354 Matrix.translateM(mEyePointModelMatrix, 0, -eyePointX, -eyePointY, |
| 441 DESKTOP_POSITION_Z); | 355 DESKTOP_POSITION_Z); |
| 442 Matrix.multiplyMM(mEyePointCombinedMatrix, 0, mViewMatrix, 0, mEyePointM
odelMatrix, 0); | 356 Matrix.multiplyMM(mEyePointCombinedMatrix, 0, mViewMatrix, 0, mEyePointM
odelMatrix, 0); |
| 443 Matrix.multiplyMM(mEyePointCombinedMatrix, 0, mProjectionMatrix, | 357 Matrix.multiplyMM(mEyePointCombinedMatrix, 0, mProjectionMatrix, |
| 444 0, mEyePointCombinedMatrix, 0); | 358 0, mEyePointCombinedMatrix, 0); |
| 445 | 359 |
| 446 mEyePoint.setCombinedMatrix(mEyePointCombinedMatrix); | 360 mEyePoint.setCombinedMatrix(mEyePointCombinedMatrix); |
| 447 mEyePoint.draw(); | 361 mEyePoint.draw(); |
| 448 } | 362 } |
| (...skipping 19 matching lines...) Expand all Loading... |
| 468 GLES20.glDrawElements(GLES20.GL_TRIANGLES, 36, GLES20.GL_UNSIGNED_BYTE, | 382 GLES20.glDrawElements(GLES20.GL_TRIANGLES, 36, GLES20.GL_UNSIGNED_BYTE, |
| 469 SKYBOX_INDICES_BYTE_BUFFER); | 383 SKYBOX_INDICES_BYTE_BUFFER); |
| 470 } | 384 } |
| 471 | 385 |
| 472 /** | 386 /** |
| 473 * Returns coordinates in units of pixels in the desktop bitmap. | 387 * Returns coordinates in units of pixels in the desktop bitmap. |
| 474 * This can be called on any thread. | 388 * This can be called on any thread. |
| 475 */ | 389 */ |
| 476 public PointF getMouseCoordinates() { | 390 public PointF getMouseCoordinates() { |
| 477 PointF result = new PointF(); | 391 PointF result = new PointF(); |
| 392 Point shapePixels = mDesktop.getShapePixels(); |
| 393 int heightPixels = shapePixels.x; |
| 394 int widthPixels = shapePixels.y; |
| 395 |
| 478 synchronized (mEyePositionLock) { | 396 synchronized (mEyePositionLock) { |
| 479 // Due to the coordinate direction, we only have to inverse x. | 397 // Due to the coordinate direction, we only have to inverse x. |
| 480 result.x = (-mEyePositionVector[0] + mHalfDesktopWidth) | 398 result.x = (-mEyePositionVector[0] + mDesktop.getHalfWidth()) |
| 481 / (2 * mHalfDesktopWidth) * mDesktopWidthPixels; | 399 / (2 * mDesktop.getHalfWidth()) * widthPixels; |
| 482 result.y = (mEyePositionVector[1] + HALF_DESKTOP_HEIGHT) | 400 result.y = (mEyePositionVector[1] + mDesktop.getHalfHeight()) |
| 483 / (2 * HALF_DESKTOP_HEIGHT) * mDesktopHeightPixels; | 401 / (2 * mDesktop.getHalfHeight()) * heightPixels; |
| 484 result.x = clamp(result.x, 0, mDesktopWidthPixels); | 402 result.x = clamp(result.x, 0, widthPixels); |
| 485 result.y = clamp(result.y, 0, mDesktopHeightPixels); | 403 result.y = clamp(result.y, 0, heightPixels); |
| 486 } | 404 } |
| 487 return result; | 405 return result; |
| 488 } | 406 } |
| 489 | 407 |
| 490 /** | 408 /** |
| 491 * Returns the passed in value if it resides within the specified range (inc
lusive). If not, | 409 * Returns the passed in value if it resides within the specified range (inc
lusive). If not, |
| 492 * it will return the closest boundary from the range. The ordering of the
boundary values | 410 * it will return the closest boundary from the range. The ordering of the
boundary values |
| 493 * does not matter. | 411 * does not matter. |
| 494 * | 412 * |
| 495 * @param value The value to be compared against the range. | 413 * @param value The value to be compared against the range. |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 533 } | 451 } |
| 534 } | 452 } |
| 535 } | 453 } |
| 536 | 454 |
| 537 /** | 455 /** |
| 538 * Return true if user is looking at the desktop. | 456 * Return true if user is looking at the desktop. |
| 539 * This method can be called on any thread. | 457 * This method can be called on any thread. |
| 540 */ | 458 */ |
| 541 public boolean isLookingAtDesktop() { | 459 public boolean isLookingAtDesktop() { |
| 542 synchronized (mEyePositionLock) { | 460 synchronized (mEyePositionLock) { |
| 543 return Math.abs(mEyePositionVector[0]) <= (mHalfDesktopWidth + EDGE_
MARGIN) | 461 return Math.abs(mEyePositionVector[0]) <= (mDesktop.getHalfWidth() +
EDGE_MARGIN) |
| 544 && Math.abs(mEyePositionVector[1]) <= (HALF_DESKTOP_HEIGHT + EDG
E_MARGIN); | 462 && Math.abs(mEyePositionVector[1]) <= (mDesktop.getHalfHeight()
+ EDGE_MARGIN); |
| 545 } | 463 } |
| 546 } | 464 } |
| 547 | 465 |
| 548 /** | 466 /** |
| 549 * Return true if user is looking at the space to the left of the desktop. | 467 * Return true if user is looking at the space to the left of the desktop. |
| 550 * This method can be called on any thread. | 468 * This method can be called on any thread. |
| 551 */ | 469 */ |
| 552 public boolean isLookingLeftOfDesktop() { | 470 public boolean isLookingLeftOfDesktop() { |
| 553 synchronized (mEyePositionLock) { | 471 synchronized (mEyePositionLock) { |
| 554 return mEyePositionVector[0] >= (mHalfDesktopWidth + EDGE_MARGIN); | 472 return mEyePositionVector[0] >= (mDesktop.getHalfWidth() + EDGE_MARG
IN); |
| 555 } | 473 } |
| 556 } | 474 } |
| 557 | 475 |
| 558 /** | 476 /** |
| 559 * Return true if user is looking at the space to the right of the desktop. | 477 * Return true if user is looking at the space to the right of the desktop. |
| 560 * This method can be called on any thread. | 478 * This method can be called on any thread. |
| 561 */ | 479 */ |
| 562 public boolean isLookingRightOfDesktop() { | 480 public boolean isLookingRightOfDesktop() { |
| 563 synchronized (mEyePositionLock) { | 481 synchronized (mEyePositionLock) { |
| 564 return mEyePositionVector[0] <= -(mHalfDesktopWidth + EDGE_MARGIN); | 482 return mEyePositionVector[0] <= -(mDesktop.getHalfWidth() + EDGE_MAR
GIN); |
| 565 } | 483 } |
| 566 } | 484 } |
| 567 | 485 |
| 568 /** | 486 /** |
| 569 * Return true if user is looking at the space above the desktop. | 487 * Return true if user is looking at the space above the desktop. |
| 570 * This method can be called on any thread. | 488 * This method can be called on any thread. |
| 571 */ | 489 */ |
| 572 public boolean isLookingAboveDesktop() { | 490 public boolean isLookingAboveDesktop() { |
| 573 synchronized (mEyePositionLock) { | 491 synchronized (mEyePositionLock) { |
| 574 return mEyePositionVector[1] <= -(HALF_DESKTOP_HEIGHT + EDGE_MARGIN)
; | 492 return mEyePositionVector[1] <= -(mDesktop.getHalfHeight() + EDGE_MA
RGIN); |
| 575 } | 493 } |
| 576 } | 494 } |
| 577 | 495 |
| 578 /** | 496 /** |
| 579 * Return true if user is looking at the space below the desktop. | 497 * Return true if user is looking at the space below the desktop. |
| 580 * This method can be called on any thread. | 498 * This method can be called on any thread. |
| 581 */ | 499 */ |
| 582 public boolean isLookingBelowDesktop() { | 500 public boolean isLookingBelowDesktop() { |
| 583 synchronized (mEyePositionLock) { | 501 synchronized (mEyePositionLock) { |
| 584 return mEyePositionVector[1] >= (HALF_DESKTOP_HEIGHT + EDGE_MARGIN); | 502 return mEyePositionVector[1] >= (mDesktop.getHalfHeight() + EDGE_MAR
GIN); |
| 585 } | 503 } |
| 586 } | 504 } |
| 587 | 505 |
| 588 /** | 506 /** |
| 589 * Get position on desktop where user is looking at. | 507 * Get position on desktop where user is looking at. |
| 590 */ | 508 */ |
| 591 private void getLookingPosition() { | 509 private void getLookingPosition() { |
| 592 synchronized (mEyePositionLock) { | 510 synchronized (mEyePositionLock) { |
| 593 if (Math.abs(mForwardVector[2]) < 0.00001f) { | 511 if (Math.abs(mForwardVector[2]) < 0.00001f) { |
| 594 mEyePositionVector[0] = Math.signum(mForwardVector[0]) * Float.M
AX_VALUE; | 512 mEyePositionVector[0] = Math.signum(mForwardVector[0]) * Float.M
AX_VALUE; |
| 595 mEyePositionVector[1] = Math.signum(mForwardVector[1]) * Float.M
AX_VALUE; | 513 mEyePositionVector[1] = Math.signum(mForwardVector[1]) * Float.M
AX_VALUE; |
| 596 } else { | 514 } else { |
| 597 mEyePositionVector[0] = mForwardVector[0] * DESKTOP_POSITION_Z /
mForwardVector[2]; | 515 mEyePositionVector[0] = mForwardVector[0] * DESKTOP_POSITION_Z /
mForwardVector[2]; |
| 598 mEyePositionVector[1] = mForwardVector[1] * DESKTOP_POSITION_Z /
mForwardVector[2]; | 516 mEyePositionVector[1] = mForwardVector[1] * DESKTOP_POSITION_Z /
mForwardVector[2]; |
| 599 } | 517 } |
| 600 mEyePositionVector[2] = DESKTOP_POSITION_Z; | 518 mEyePositionVector[2] = DESKTOP_POSITION_Z; |
| 601 } | 519 } |
| 602 } | 520 } |
| 603 | 521 |
| 604 /** | 522 /** |
| 605 * Link desktop texture with textureDataHandle if {@link mReloadTexture} is
true. | 523 * Link desktop texture with {@link CardboardActivityDesktop} if {@link mRel
oadTexture} is true. |
| 606 * @param textureDataHandle the handle we want attach texture to | 524 * @param textureDataHandle the handle we want attach texture to |
| 607 */ | 525 */ |
| 608 private void maybeLoadTexture(int textureDataHandle) { | 526 private void maybeLoadDesktopTexture() { |
| 609 synchronized (mReloadTextureLock) { | 527 synchronized (mReloadTextureLock) { |
| 610 if (!mReloadTexture) { | 528 if (!mReloadTexture) { |
| 611 return; | 529 return; |
| 612 } | 530 } |
| 613 } | 531 } |
| 614 | 532 |
| 615 // TODO(shichengfeng): Record the time desktop drawing takes. | 533 // TODO(shichengfeng): Record the time desktop drawing takes. |
| 616 Bitmap bitmap = JniInterface.getVideoFrame(); | 534 Bitmap bitmap = JniInterface.getVideoFrame(); |
| 617 | 535 |
| 618 if (bitmap == null) { | 536 if (bitmap == null) { |
| 619 // This can happen if the client is connected, but a complete video
frame has not yet | 537 // This can happen if the client is connected, but a complete video
frame has not yet |
| 620 // been decoded. | 538 // been decoded. |
| 621 return; | 539 return; |
| 622 } | 540 } |
| 623 | 541 |
| 624 synchronized (mEyePositionLock) { | 542 mDesktop.updateVideoFrameData(bitmap); |
| 625 mDesktopHeightPixels = bitmap.getHeight(); | |
| 626 mDesktopWidthPixels = bitmap.getWidth(); | |
| 627 } | |
| 628 | |
| 629 updateDesktopCoordinatesBuffer(bitmap); | |
| 630 TextureHelper.linkTexture(textureDataHandle, bitmap); | |
| 631 | 543 |
| 632 synchronized (mReloadTextureLock) { | 544 synchronized (mReloadTextureLock) { |
| 633 mReloadTexture = false; | 545 mReloadTexture = false; |
| 634 } | 546 } |
| 635 } | 547 } |
| 636 | 548 |
| 637 /** | 549 /** |
| 638 * Convert float array to a FloatBuffer for use in OpenGL calls. | 550 * Convert float array to a FloatBuffer for use in OpenGL calls. |
| 639 */ | 551 */ |
| 640 private static FloatBuffer makeFloatBuffer(float[] data) { | 552 public static FloatBuffer makeFloatBuffer(float[] data) { |
| 641 FloatBuffer result = ByteBuffer | 553 FloatBuffer result = ByteBuffer |
| 642 .allocateDirect(data.length * BYTE_PER_FLOAT) | 554 .allocateDirect(data.length * BYTE_PER_FLOAT) |
| 643 .order(ByteOrder.nativeOrder()).asFloatBuffer(); | 555 .order(ByteOrder.nativeOrder()).asFloatBuffer(); |
| 644 result.put(data).position(0); | 556 result.put(data).position(0); |
| 645 return result; | 557 return result; |
| 646 } | 558 } |
| 647 | 559 |
| 648 /** | 560 /** |
| 649 * Update the desktop coordinates based on the new bitmap. Note here we fix
the | |
| 650 * height of the desktop and vary width accordingly. | |
| 651 */ | |
| 652 private void updateDesktopCoordinatesBuffer(Bitmap bitmap) { | |
| 653 int width = bitmap.getWidth(); | |
| 654 int height = bitmap.getHeight(); | |
| 655 float newHalfDesktopWidth = width * HALF_DESKTOP_HEIGHT / height; | |
| 656 if (Math.abs(mHalfDesktopWidth - newHalfDesktopWidth) > 0.0001) { | |
| 657 mHalfDesktopWidth = newHalfDesktopWidth; | |
| 658 mDesktopCoordinates = makeFloatBuffer(new float[] { | |
| 659 // Desktop model coordinates. | |
| 660 -mHalfDesktopWidth, HALF_DESKTOP_HEIGHT, 0.0f, | |
| 661 -mHalfDesktopWidth, -HALF_DESKTOP_HEIGHT, 0.0f, | |
| 662 mHalfDesktopWidth, HALF_DESKTOP_HEIGHT, 0.0f, | |
| 663 -mHalfDesktopWidth, -HALF_DESKTOP_HEIGHT, 0.0f, | |
| 664 mHalfDesktopWidth, -HALF_DESKTOP_HEIGHT, 0.0f, | |
| 665 mHalfDesktopWidth, HALF_DESKTOP_HEIGHT, 0.0f | |
| 666 }); | |
| 667 } | |
| 668 } | |
| 669 | |
| 670 /** | |
| 671 * Decode all skybox images to Bitmap files and return them. | 561 * Decode all skybox images to Bitmap files and return them. |
| 672 * Only call this method when we have complete skybox images. | 562 * Only call this method when we have complete skybox images. |
| 673 * @throws DecodeFileException if BitmapFactory fails to decode file. | 563 * @throws DecodeFileException if BitmapFactory fails to decode file. |
| 674 */ | 564 */ |
| 675 private Bitmap[] decodeSkyboxImages() throws DecodeFileException { | 565 private Bitmap[] decodeSkyboxImages() throws DecodeFileException { |
| 676 Bitmap[] result = new Bitmap[SKYBOX_IMAGE_NAMES.length]; | 566 Bitmap[] result = new Bitmap[SKYBOX_IMAGE_NAMES.length]; |
| 677 String fileDirectory = mDownloadManager.getDownloadDirectory(); | 567 String fileDirectory = mDownloadManager.getDownloadDirectory(); |
| 678 for (int i = 0; i < SKYBOX_IMAGE_NAMES.length; i++) { | 568 for (int i = 0; i < SKYBOX_IMAGE_NAMES.length; i++) { |
| 679 result[i] = BitmapFactory.decodeFile(fileDirectory + "/" + SKYBOX_IM
AGE_NAMES[i]); | 569 result[i] = BitmapFactory.decodeFile(fileDirectory + "/" + SKYBOX_IM
AGE_NAMES[i]); |
| 680 if (result[i] == null) { | 570 if (result[i] == null) { |
| (...skipping 28 matching lines...) Expand all Loading... |
| 709 image.recycle(); | 599 image.recycle(); |
| 710 } | 600 } |
| 711 } | 601 } |
| 712 | 602 |
| 713 /** | 603 /** |
| 714 * Exception when BitmapFactory fails to decode file. | 604 * Exception when BitmapFactory fails to decode file. |
| 715 */ | 605 */ |
| 716 private static class DecodeFileException extends Exception { | 606 private static class DecodeFileException extends Exception { |
| 717 } | 607 } |
| 718 } | 608 } |
| OLD | NEW |