Chromium Code Reviews| 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.PointF; | 10 import android.graphics.PointF; |
| (...skipping 29 matching lines...) Expand all Loading... | |
| 40 private static final float DESKTOP_POSITION_Y = 0.0f; | 40 private static final float DESKTOP_POSITION_Y = 0.0f; |
| 41 private static final float DESKTOP_POSITION_Z = -2.0f; | 41 private static final float DESKTOP_POSITION_Z = -2.0f; |
| 42 private static final float HALF_SKYBOX_SIZE = 100.0f; | 42 private static final float HALF_SKYBOX_SIZE = 100.0f; |
| 43 private static final float VIEW_POSITION_MIN = -1.0f; | 43 private static final float VIEW_POSITION_MIN = -1.0f; |
| 44 private static final float VIEW_POSITION_MAX = 3.0f; | 44 private static final float VIEW_POSITION_MAX = 3.0f; |
| 45 | 45 |
| 46 // Allows user to click even when looking outside the desktop | 46 // Allows user to click even when looking outside the desktop |
| 47 // but within edge margin. | 47 // but within edge margin. |
| 48 private static final float EDGE_MARGIN = 0.1f; | 48 private static final float EDGE_MARGIN = 0.1f; |
| 49 | 49 |
| 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. | 50 // Distance to move camera each time. |
| 54 private static final float CAMERA_MOTION_STEP = 0.5f; | 51 private static final float CAMERA_MOTION_STEP = 0.5f; |
| 55 | 52 |
| 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[] { | 53 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 | 54 -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 | 55 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 | 56 -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 | 57 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 | 58 -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 | 59 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 | 60 -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 | 61 HALF_SKYBOX_SIZE, -HALF_SKYBOX_SIZE, -HALF_SKYBOX_SIZE // (7) Botto m-right far |
| 75 }); | 62 }); |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 93 | 80 |
| 94 // Top | 81 // Top |
| 95 5, 1, 4, | 82 5, 1, 4, |
| 96 4, 1, 0, | 83 4, 1, 0, |
| 97 | 84 |
| 98 // Bottom | 85 // Bottom |
| 99 6, 2, 7, | 86 6, 2, 7, |
| 100 7, 2, 3 | 87 7, 2, 3 |
| 101 }); | 88 }); |
| 102 | 89 |
| 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 = | 90 private static final String SKYBOX_VERTEX_SHADER = |
| 129 "uniform mat4 u_CombinedMatrix;" | 91 "uniform mat4 u_CombinedMatrix;" |
| 130 + "attribute vec3 a_Position;" | 92 + "attribute vec3 a_Position;" |
| 131 + "varying vec3 v_Position;" | 93 + "varying vec3 v_Position;" |
| 132 + "void main() {" | 94 + "void main() {" |
| 133 + " v_Position = a_Position;" | 95 + " v_Position = a_Position;" |
| 134 // Make sure to convert from the right-handed coordinate system of t he | 96 // 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, | 97 // 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. | 98 // our cube map will still work but everything will be flipped. |
| 137 + " v_Position.z = -v_Position.z;" | 99 + " 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", | 120 "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" | 121 "https://dl.google.com/chrome-remote-desktop/android-assets/room_front.p ng" |
| 160 }; | 122 }; |
| 161 | 123 |
| 162 private static final String[] SKYBOX_IMAGE_NAMES = new String[] { | 124 private static final String[] SKYBOX_IMAGE_NAMES = new String[] { |
| 163 "skybox_left", "skybox_right", "skybox_bottom", "skybox_top", "skybox_ba ck", "skybox_front" | 125 "skybox_left", "skybox_right", "skybox_bottom", "skybox_top", "skybox_ba ck", "skybox_front" |
| 164 }; | 126 }; |
| 165 | 127 |
| 166 private final Activity mActivity; | 128 private final Activity mActivity; |
| 167 | 129 |
| 168 private float mHalfDesktopWidth; | |
| 169 private float mCameraPosition; | 130 private float mCameraPosition; |
| 170 | 131 |
| 171 // Lock to allow multithreaded access to mCameraPosition. | 132 // Lock to allow multithreaded access to mCameraPosition. |
| 172 private Object mCameraPositionLock = new Object(); | 133 private Object mCameraPositionLock = new Object(); |
| 173 | 134 |
| 174 private float[] mCameraMatrix; | 135 private float[] mCameraMatrix; |
| 175 private float[] mViewMatrix; | 136 private float[] mViewMatrix; |
| 176 private float[] mProjectionMatrix; | 137 private float[] mProjectionMatrix; |
| 177 | 138 |
| 178 // Make matrix member variable to avoid unnecessary initialization. | 139 // Make matrix member variable to avoid unnecessary initialization. |
| 179 private float[] mDesktopModelMatrix; | 140 private float[] mDesktopModelMatrix; |
| 180 private float[] mDesktopCombinedMatrix; | 141 private float[] mDesktopCombinedMatrix; |
| 181 private float[] mEyePointModelMatrix; | 142 private float[] mEyePointModelMatrix; |
| 182 private float[] mEyePointCombinedMatrix; | 143 private float[] mEyePointCombinedMatrix; |
| 183 private float[] mSkyboxModelMatrix; | 144 private float[] mSkyboxModelMatrix; |
| 184 private float[] mSkyboxCombinedMatrix; | 145 private float[] mSkyboxCombinedMatrix; |
| 185 | 146 |
| 186 // Direction that user is looking towards. | 147 // Direction that user is looking towards. |
| 187 private float[] mForwardVector; | 148 private float[] mForwardVector; |
| 188 | 149 |
| 189 // Eye position in desktop. | 150 // Eye position in desktop. |
| 190 private float[] mEyePositionVector; | 151 private float[] mEyePositionVector; |
| 191 | 152 |
| 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; | 153 private int mSkyboxVertexShaderHandle; |
| 201 private int mSkyboxFragmentShaderHandle; | 154 private int mSkyboxFragmentShaderHandle; |
| 202 private int mSkyboxProgramHandle; | 155 private int mSkyboxProgramHandle; |
| 203 private int mSkyboxPositionHandle; | 156 private int mSkyboxPositionHandle; |
| 204 private int mSkyboxCombinedMatrixHandle; | 157 private int mSkyboxCombinedMatrixHandle; |
| 205 private int mSkyboxTextureUnitHandle; | 158 private int mSkyboxTextureUnitHandle; |
| 206 private int mSkyboxTextureDataHandle; | 159 private int mSkyboxTextureDataHandle; |
| 160 private CardboardActivityDesktop mDesktop; | |
| 207 private CardboardActivityEyePoint mEyePoint; | 161 private CardboardActivityEyePoint mEyePoint; |
| 208 | 162 |
| 209 // Flag to indicate whether reload the desktop texture or not. | 163 // Flag to indicate whether reload the desktop texture or not. |
| 210 private boolean mReloadTexture; | 164 private boolean mReloadTexture; |
| 211 | 165 |
| 212 /** Lock to allow multithreaded access to mReloadTexture. */ | 166 /** Lock to allow multithreaded access to mReloadTexture. */ |
| 213 private Object mReloadTextureLock = new Object(); | 167 private Object mReloadTextureLock = new Object(); |
| 214 | 168 |
| 215 // Lock for eye position related operations. | 169 // Lock for eye position related operations. |
| 216 // This protects access to mEyePositionVector as well as mDesktop{Height/Wid th}Pixels. | 170 // This protects access to mEyePositionVector as well as mDesktop{Height/Wid th}Pixels. |
|
Lambros
2015/08/20 19:07:27
... as well as mDesktop.
shichengfeng
2015/08/20 20:02:59
Done.
| |
| 217 private Object mEyePositionLock = new Object(); | 171 private Object mEyePositionLock = new Object(); |
| 218 | 172 |
| 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 | 173 // Flag to signal that the skybox images are fully decoded and should be loa ded |
| 225 // into the OpenGL textures. | 174 // into the OpenGL textures. |
| 226 private boolean mLoadSkyboxImagesTexture; | 175 private boolean mLoadSkyboxImagesTexture; |
| 227 | 176 |
| 228 // Lock to allow multithreaded access to mLoadSkyboxImagesTexture. | 177 // Lock to allow multithreaded access to mLoadSkyboxImagesTexture. |
| 229 private Object mLoadSkyboxImagesTextureLock = new Object(); | 178 private Object mLoadSkyboxImagesTextureLock = new Object(); |
| 230 | 179 |
| 231 private ChromotingDownloadManager mDownloadManager; | 180 private ChromotingDownloadManager mDownloadManager; |
| 232 | 181 |
| 233 public CardboardDesktopRenderer(Activity activity) { | 182 public CardboardDesktopRenderer(Activity activity) { |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 278 public void onSurfaceCreated(EGLConfig config) { | 227 public void onSurfaceCreated(EGLConfig config) { |
| 279 // Set the background clear color to black. | 228 // Set the background clear color to black. |
| 280 GLES20.glClearColor(0.0f, 0.0f, 0.0f, 0.0f); | 229 GLES20.glClearColor(0.0f, 0.0f, 0.0f, 0.0f); |
| 281 | 230 |
| 282 // Use culling to remove back faces. | 231 // Use culling to remove back faces. |
| 283 GLES20.glEnable(GLES20.GL_CULL_FACE); | 232 GLES20.glEnable(GLES20.GL_CULL_FACE); |
| 284 | 233 |
| 285 // Enable depth testing. | 234 // Enable depth testing. |
| 286 GLES20.glEnable(GLES20.GL_DEPTH_TEST); | 235 GLES20.glEnable(GLES20.GL_DEPTH_TEST); |
| 287 | 236 |
| 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. | 237 // Set handlers for skybox drawing. |
| 303 GLES20.glEnable(GLES20.GL_TEXTURE_CUBE_MAP); | 238 GLES20.glEnable(GLES20.GL_TEXTURE_CUBE_MAP); |
| 304 mSkyboxVertexShaderHandle = | 239 mSkyboxVertexShaderHandle = |
| 305 ShaderHelper.compileShader(GLES20.GL_VERTEX_SHADER, SKYBOX_VERTE X_SHADER); | 240 ShaderHelper.compileShader(GLES20.GL_VERTEX_SHADER, SKYBOX_VERTE X_SHADER); |
| 306 mSkyboxFragmentShaderHandle = | 241 mSkyboxFragmentShaderHandle = |
| 307 ShaderHelper.compileShader(GLES20.GL_FRAGMENT_SHADER, SKYBOX_FRA GMENT_SHADER); | 242 ShaderHelper.compileShader(GLES20.GL_FRAGMENT_SHADER, SKYBOX_FRA GMENT_SHADER); |
| 308 mSkyboxProgramHandle = ShaderHelper.createAndLinkProgram(mSkyboxVertexSh aderHandle, | 243 mSkyboxProgramHandle = ShaderHelper.createAndLinkProgram(mSkyboxVertexSh aderHandle, |
| 309 mSkyboxFragmentShaderHandle, | 244 mSkyboxFragmentShaderHandle, |
| 310 new String[] {"a_Position", "u_CombinedMatrix", "u_TextureUnit"} ); | 245 new String[] {"a_Position", "u_CombinedMatrix", "u_TextureUnit"} ); |
| 311 mSkyboxPositionHandle = | 246 mSkyboxPositionHandle = |
| 312 GLES20.glGetAttribLocation(mSkyboxProgramHandle, "a_Position"); | 247 GLES20.glGetAttribLocation(mSkyboxProgramHandle, "a_Position"); |
| 313 mSkyboxCombinedMatrixHandle = | 248 mSkyboxCombinedMatrixHandle = |
| 314 GLES20.glGetUniformLocation(mSkyboxProgramHandle, "u_CombinedMat rix"); | 249 GLES20.glGetUniformLocation(mSkyboxProgramHandle, "u_CombinedMat rix"); |
| 315 mSkyboxTextureUnitHandle = | 250 mSkyboxTextureUnitHandle = |
| 316 GLES20.glGetUniformLocation(mSkyboxProgramHandle, "u_TextureUnit "); | 251 GLES20.glGetUniformLocation(mSkyboxProgramHandle, "u_TextureUnit "); |
| 317 mSkyboxTextureDataHandle = TextureHelper.createTextureHandle(); | 252 mSkyboxTextureDataHandle = TextureHelper.createTextureHandle(); |
| 318 | 253 |
| 254 mDesktop = new CardboardActivityDesktop(); | |
| 319 mEyePoint = new CardboardActivityEyePoint(); | 255 mEyePoint = new CardboardActivityEyePoint(); |
| 320 } | 256 } |
| 321 | 257 |
| 322 @Override | 258 @Override |
| 323 public void onSurfaceChanged(int width, int height) { | 259 public void onSurfaceChanged(int width, int height) { |
| 324 } | 260 } |
| 325 | 261 |
| 326 @Override | 262 @Override |
| 327 public void onNewFrame(HeadTransform headTransform) { | 263 public void onNewFrame(HeadTransform headTransform) { |
| 328 // Position the eye at the origin. | 264 // Position the eye at the origin. |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 340 | 276 |
| 341 // Set our up vector. This is where our head would be pointing were we h olding the camera. | 277 // Set our up vector. This is where our head would be pointing were we h olding the camera. |
| 342 float upX = 0.0f; | 278 float upX = 0.0f; |
| 343 float upY = 1.0f; | 279 float upY = 1.0f; |
| 344 float upZ = 0.0f; | 280 float upZ = 0.0f; |
| 345 | 281 |
| 346 Matrix.setLookAtM(mCameraMatrix, 0, eyeX, eyeY, eyeZ, lookX, lookY, look Z, upX, upY, upZ); | 282 Matrix.setLookAtM(mCameraMatrix, 0, eyeX, eyeY, eyeZ, lookX, lookY, look Z, upX, upY, upZ); |
| 347 | 283 |
| 348 headTransform.getForwardVector(mForwardVector, 0); | 284 headTransform.getForwardVector(mForwardVector, 0); |
| 349 getLookingPosition(); | 285 getLookingPosition(); |
| 350 maybeLoadTexture(mTextureDataHandle); | 286 maybeLoadDesktopTexture(); |
| 351 maybeLoadCubeMapAndCleanImages(mSkyboxTextureDataHandle); | 287 maybeLoadCubeMapAndCleanImages(mSkyboxTextureDataHandle); |
| 352 } | 288 } |
| 353 | 289 |
| 354 @Override | 290 @Override |
| 355 public void onDrawEye(Eye eye) { | 291 public void onDrawEye(Eye eye) { |
| 356 GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT); | 292 GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT); |
| 357 | 293 |
| 358 // Apply the eye transformation to the camera. | 294 // Apply the eye transformation to the camera. |
| 359 Matrix.multiplyMM(mViewMatrix, 0, eye.getEyeView(), 0, mCameraMatrix, 0) ; | 295 Matrix.multiplyMM(mViewMatrix, 0, eye.getEyeView(), 0, mCameraMatrix, 0) ; |
| 360 | 296 |
| 361 mProjectionMatrix = eye.getPerspective(Z_NEAR, Z_FAR); | 297 mProjectionMatrix = eye.getPerspective(Z_NEAR, Z_FAR); |
| 362 | 298 |
| 363 drawSkybox(); | 299 drawSkybox(); |
| 364 drawDesktop(); | 300 drawDesktop(); |
| 365 drawEyePoint(); | 301 drawEyePoint(); |
| 366 } | 302 } |
| 367 | 303 |
| 368 @Override | 304 @Override |
| 369 public void onRendererShutdown() { | 305 public void onRendererShutdown() { |
| 370 GLES20.glDeleteShader(mDesktopVertexShaderHandle); | 306 mDesktop.cleanup(); |
| 371 GLES20.glDeleteShader(mDesktopFragmentShaderHandle); | |
| 372 mEyePoint.cleanup(); | 307 mEyePoint.cleanup(); |
| 373 GLES20.glDeleteShader(mSkyboxVertexShaderHandle); | 308 GLES20.glDeleteShader(mSkyboxVertexShaderHandle); |
| 374 GLES20.glDeleteShader(mSkyboxFragmentShaderHandle); | 309 GLES20.glDeleteShader(mSkyboxFragmentShaderHandle); |
| 375 GLES20.glDeleteTextures(1, new int[] {mTextureDataHandle}, 0); | |
| 376 GLES20.glDeleteTextures(1, new int[] {mSkyboxTextureDataHandle}, 0); | 310 GLES20.glDeleteTextures(1, new int[] {mSkyboxTextureDataHandle}, 0); |
| 377 mActivity.runOnUiThread(new Runnable() { | 311 mActivity.runOnUiThread(new Runnable() { |
| 378 public void run() { | 312 public void run() { |
| 379 mDownloadManager.close(); | 313 mDownloadManager.close(); |
| 380 } | 314 } |
| 381 }); | 315 }); |
| 382 } | 316 } |
| 383 | 317 |
| 384 @Override | 318 @Override |
| 385 public void onFinishFrame(Viewport viewport) { | 319 public void onFinishFrame(Viewport viewport) { |
| 386 } | 320 } |
| 387 | 321 |
| 388 private void drawDesktop() { | 322 private void drawDesktop() { |
| 389 GLES20.glUseProgram(mProgramHandle); | 323 if (!mDesktop.hasImageFrame()) { |
| 324 // This can happen if the client is connected, but a complete video frame has not yet | |
| 325 // been decoded. | |
| 326 return; | |
| 327 } | |
| 390 | 328 |
| 391 // Translate the desktop model. | |
| 392 Matrix.setIdentityM(mDesktopModelMatrix, 0); | 329 Matrix.setIdentityM(mDesktopModelMatrix, 0); |
| 393 Matrix.translateM(mDesktopModelMatrix, 0, DESKTOP_POSITION_X, | 330 Matrix.translateM(mDesktopModelMatrix, 0, DESKTOP_POSITION_X, |
| 394 DESKTOP_POSITION_Y, DESKTOP_POSITION_Z); | 331 DESKTOP_POSITION_Y, DESKTOP_POSITION_Z); |
| 395 | 332 |
| 396 // Pass in Model View Matrix and Model View Project Matrix. | 333 // Pass in Model View Matrix and Model View Project Matrix. |
| 397 Matrix.multiplyMM(mDesktopCombinedMatrix, 0, mViewMatrix, 0, mDesktopMod elMatrix, 0); | 334 Matrix.multiplyMM(mDesktopCombinedMatrix, 0, mViewMatrix, 0, mDesktopMod elMatrix, 0); |
| 398 Matrix.multiplyMM(mDesktopCombinedMatrix, 0, mProjectionMatrix, | 335 Matrix.multiplyMM(mDesktopCombinedMatrix, 0, mProjectionMatrix, |
| 399 0, mDesktopCombinedMatrix, 0); | 336 0, mDesktopCombinedMatrix, 0); |
| 337 mDesktop.setCombinedMatrix(mDesktopCombinedMatrix); | |
| 400 | 338 |
| 401 // Pass in model view project matrix. | 339 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 } | 340 } |
| 429 | 341 |
| 430 private void drawEyePoint() { | 342 private void drawEyePoint() { |
| 431 if (!isLookingAtDesktop()) { | 343 if (!isLookingAtDesktop()) { |
| 432 return; | 344 return; |
| 433 } | 345 } |
| 434 | 346 |
| 435 float eyePointX = clamp(mEyePositionVector[0], -mHalfDesktopWidth, | 347 float eyePointX = clamp(mEyePositionVector[0], -mDesktop.getHalfWidth(), |
| 436 mHalfDesktopWidth); | 348 mDesktop.getHalfWidth()); |
| 437 float eyePointY = clamp(mEyePositionVector[1], -HALF_DESKTOP_HEIGHT, | 349 float eyePointY = clamp(mEyePositionVector[1], -mDesktop.getHalfHeight() , |
| 438 HALF_DESKTOP_HEIGHT); | 350 mDesktop.getHalfHeight()); |
| 439 Matrix.setIdentityM(mEyePointModelMatrix, 0); | 351 Matrix.setIdentityM(mEyePointModelMatrix, 0); |
| 440 Matrix.translateM(mEyePointModelMatrix, 0, -eyePointX, -eyePointY, | 352 Matrix.translateM(mEyePointModelMatrix, 0, -eyePointX, -eyePointY, |
| 441 DESKTOP_POSITION_Z); | 353 DESKTOP_POSITION_Z); |
| 442 Matrix.multiplyMM(mEyePointCombinedMatrix, 0, mViewMatrix, 0, mEyePointM odelMatrix, 0); | 354 Matrix.multiplyMM(mEyePointCombinedMatrix, 0, mViewMatrix, 0, mEyePointM odelMatrix, 0); |
| 443 Matrix.multiplyMM(mEyePointCombinedMatrix, 0, mProjectionMatrix, | 355 Matrix.multiplyMM(mEyePointCombinedMatrix, 0, mProjectionMatrix, |
| 444 0, mEyePointCombinedMatrix, 0); | 356 0, mEyePointCombinedMatrix, 0); |
| 445 | 357 |
| 446 mEyePoint.setCombinedMatrix(mEyePointCombinedMatrix); | 358 mEyePoint.setCombinedMatrix(mEyePointCombinedMatrix); |
| 447 mEyePoint.draw(); | 359 mEyePoint.draw(); |
| 448 } | 360 } |
| (...skipping 21 matching lines...) Expand all Loading... | |
| 470 } | 382 } |
| 471 | 383 |
| 472 /** | 384 /** |
| 473 * Returns coordinates in units of pixels in the desktop bitmap. | 385 * Returns coordinates in units of pixels in the desktop bitmap. |
| 474 * This can be called on any thread. | 386 * This can be called on any thread. |
| 475 */ | 387 */ |
| 476 public PointF getMouseCoordinates() { | 388 public PointF getMouseCoordinates() { |
| 477 PointF result = new PointF(); | 389 PointF result = new PointF(); |
| 478 synchronized (mEyePositionLock) { | 390 synchronized (mEyePositionLock) { |
| 479 // Due to the coordinate direction, we only have to inverse x. | 391 // Due to the coordinate direction, we only have to inverse x. |
| 480 result.x = (-mEyePositionVector[0] + mHalfDesktopWidth) | 392 result.x = (-mEyePositionVector[0] + mDesktop.getHalfWidth()) |
| 481 / (2 * mHalfDesktopWidth) * mDesktopWidthPixels; | 393 / (2 * mDesktop.getHalfWidth()) * mDesktop.getWidthPixels(); |
| 482 result.y = (mEyePositionVector[1] + HALF_DESKTOP_HEIGHT) | 394 result.y = (mEyePositionVector[1] + mDesktop.getHalfHeight()) |
| 483 / (2 * HALF_DESKTOP_HEIGHT) * mDesktopHeightPixels; | 395 / (2 * mDesktop.getHalfHeight()) * mDesktop.getHeightPixels( ); |
| 484 result.x = clamp(result.x, 0, mDesktopWidthPixels); | 396 result.x = clamp(result.x, 0, mDesktop.getWidthPixels()); |
| 485 result.y = clamp(result.y, 0, mDesktopHeightPixels); | 397 result.y = clamp(result.y, 0, mDesktop.getHeightPixels()); |
| 486 } | 398 } |
| 487 return result; | 399 return result; |
| 488 } | 400 } |
| 489 | 401 |
| 490 /** | 402 /** |
| 491 * Returns the passed in value if it resides within the specified range (inc lusive). If not, | 403 * 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 | 404 * it will return the closest boundary from the range. The ordering of the boundary values |
| 493 * does not matter. | 405 * does not matter. |
| 494 * | 406 * |
| 495 * @param value The value to be compared against the range. | 407 * @param value The value to be compared against the range. |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 533 } | 445 } |
| 534 } | 446 } |
| 535 } | 447 } |
| 536 | 448 |
| 537 /** | 449 /** |
| 538 * Return true if user is looking at the desktop. | 450 * Return true if user is looking at the desktop. |
| 539 * This method can be called on any thread. | 451 * This method can be called on any thread. |
| 540 */ | 452 */ |
| 541 public boolean isLookingAtDesktop() { | 453 public boolean isLookingAtDesktop() { |
| 542 synchronized (mEyePositionLock) { | 454 synchronized (mEyePositionLock) { |
| 543 return Math.abs(mEyePositionVector[0]) <= (mHalfDesktopWidth + EDGE_ MARGIN) | 455 return Math.abs(mEyePositionVector[0]) <= (mDesktop.getHalfWidth() + EDGE_MARGIN) |
| 544 && Math.abs(mEyePositionVector[1]) <= (HALF_DESKTOP_HEIGHT + EDG E_MARGIN); | 456 && Math.abs(mEyePositionVector[1]) <= (mDesktop.getHalfHeight() + EDGE_MARGIN); |
| 545 } | 457 } |
| 546 } | 458 } |
| 547 | 459 |
| 548 /** | 460 /** |
| 549 * Return true if user is looking at the space to the left of the desktop. | 461 * Return true if user is looking at the space to the left of the desktop. |
| 550 * This method can be called on any thread. | 462 * This method can be called on any thread. |
| 551 */ | 463 */ |
| 552 public boolean isLookingLeftOfDesktop() { | 464 public boolean isLookingLeftOfDesktop() { |
| 553 synchronized (mEyePositionLock) { | 465 synchronized (mEyePositionLock) { |
| 554 return mEyePositionVector[0] >= (mHalfDesktopWidth + EDGE_MARGIN); | 466 return mEyePositionVector[0] >= (mDesktop.getHalfWidth() + EDGE_MARG IN); |
| 555 } | 467 } |
| 556 } | 468 } |
| 557 | 469 |
| 558 /** | 470 /** |
| 559 * Return true if user is looking at the space to the right of the desktop. | 471 * Return true if user is looking at the space to the right of the desktop. |
| 560 * This method can be called on any thread. | 472 * This method can be called on any thread. |
| 561 */ | 473 */ |
| 562 public boolean isLookingRightOfDesktop() { | 474 public boolean isLookingRightOfDesktop() { |
| 563 synchronized (mEyePositionLock) { | 475 synchronized (mEyePositionLock) { |
| 564 return mEyePositionVector[0] <= -(mHalfDesktopWidth + EDGE_MARGIN); | 476 return mEyePositionVector[0] <= -(mDesktop.getHalfWidth() + EDGE_MAR GIN); |
| 565 } | 477 } |
| 566 } | 478 } |
| 567 | 479 |
| 568 /** | 480 /** |
| 569 * Return true if user is looking at the space above the desktop. | 481 * Return true if user is looking at the space above the desktop. |
| 570 * This method can be called on any thread. | 482 * This method can be called on any thread. |
| 571 */ | 483 */ |
| 572 public boolean isLookingAboveDesktop() { | 484 public boolean isLookingAboveDesktop() { |
| 573 synchronized (mEyePositionLock) { | 485 synchronized (mEyePositionLock) { |
| 574 return mEyePositionVector[1] <= -(HALF_DESKTOP_HEIGHT + EDGE_MARGIN) ; | 486 return mEyePositionVector[1] <= -(mDesktop.getHalfHeight() + EDGE_MA RGIN); |
| 575 } | 487 } |
| 576 } | 488 } |
| 577 | 489 |
| 578 /** | 490 /** |
| 579 * Return true if user is looking at the space below the desktop. | 491 * Return true if user is looking at the space below the desktop. |
| 580 * This method can be called on any thread. | 492 * This method can be called on any thread. |
| 581 */ | 493 */ |
| 582 public boolean isLookingBelowDesktop() { | 494 public boolean isLookingBelowDesktop() { |
| 583 synchronized (mEyePositionLock) { | 495 synchronized (mEyePositionLock) { |
| 584 return mEyePositionVector[1] >= (HALF_DESKTOP_HEIGHT + EDGE_MARGIN); | 496 return mEyePositionVector[1] >= (mDesktop.getHalfHeight() + EDGE_MAR GIN); |
| 585 } | 497 } |
| 586 } | 498 } |
| 587 | 499 |
| 588 /** | 500 /** |
| 589 * Get position on desktop where user is looking at. | 501 * Get position on desktop where user is looking at. |
| 590 */ | 502 */ |
| 591 private void getLookingPosition() { | 503 private void getLookingPosition() { |
| 592 synchronized (mEyePositionLock) { | 504 synchronized (mEyePositionLock) { |
| 593 if (Math.abs(mForwardVector[2]) < 0.00001f) { | 505 if (Math.abs(mForwardVector[2]) < 0.00001f) { |
| 594 mEyePositionVector[0] = Math.signum(mForwardVector[0]) * Float.M AX_VALUE; | 506 mEyePositionVector[0] = Math.signum(mForwardVector[0]) * Float.M AX_VALUE; |
| 595 mEyePositionVector[1] = Math.signum(mForwardVector[1]) * Float.M AX_VALUE; | 507 mEyePositionVector[1] = Math.signum(mForwardVector[1]) * Float.M AX_VALUE; |
| 596 } else { | 508 } else { |
| 597 mEyePositionVector[0] = mForwardVector[0] * DESKTOP_POSITION_Z / mForwardVector[2]; | 509 mEyePositionVector[0] = mForwardVector[0] * DESKTOP_POSITION_Z / mForwardVector[2]; |
| 598 mEyePositionVector[1] = mForwardVector[1] * DESKTOP_POSITION_Z / mForwardVector[2]; | 510 mEyePositionVector[1] = mForwardVector[1] * DESKTOP_POSITION_Z / mForwardVector[2]; |
| 599 } | 511 } |
| 600 mEyePositionVector[2] = DESKTOP_POSITION_Z; | 512 mEyePositionVector[2] = DESKTOP_POSITION_Z; |
| 601 } | 513 } |
| 602 } | 514 } |
| 603 | 515 |
| 604 /** | 516 /** |
| 605 * Link desktop texture with textureDataHandle if {@link mReloadTexture} is true. | 517 * Link desktop texture with {@link CardboardActivityDesktop} if {@link mRel oadTexture} is true. |
| 606 * @param textureDataHandle the handle we want attach texture to | 518 * @param textureDataHandle the handle we want attach texture to |
| 607 */ | 519 */ |
| 608 private void maybeLoadTexture(int textureDataHandle) { | 520 private void maybeLoadDesktopTexture() { |
| 609 synchronized (mReloadTextureLock) { | 521 synchronized (mReloadTextureLock) { |
| 610 if (!mReloadTexture) { | 522 if (!mReloadTexture) { |
| 611 return; | 523 return; |
| 612 } | 524 } |
| 613 } | 525 } |
| 614 | 526 |
| 615 // TODO(shichengfeng): Record the time desktop drawing takes. | 527 // TODO(shichengfeng): Record the time desktop drawing takes. |
| 616 Bitmap bitmap = JniInterface.getVideoFrame(); | 528 Bitmap bitmap = JniInterface.getVideoFrame(); |
| 617 | 529 |
| 618 if (bitmap == null) { | 530 if (bitmap == null) { |
| 619 // This can happen if the client is connected, but a complete video frame has not yet | 531 // This can happen if the client is connected, but a complete video frame has not yet |
| 620 // been decoded. | 532 // been decoded. |
| 621 return; | 533 return; |
| 622 } | 534 } |
| 623 | 535 |
| 624 synchronized (mEyePositionLock) { | 536 synchronized (mEyePositionLock) { |
| 625 mDesktopHeightPixels = bitmap.getHeight(); | 537 mDesktop.setHeightPixels(bitmap.getHeight()); |
| 626 mDesktopWidthPixels = bitmap.getWidth(); | 538 mDesktop.setWidthPixels(bitmap.getWidth()); |
| 627 } | 539 } |
| 628 | 540 |
| 629 updateDesktopCoordinatesBuffer(bitmap); | 541 mDesktop.updateFrameData(bitmap); |
| 630 TextureHelper.linkTexture(textureDataHandle, bitmap); | 542 mDesktop.setTexture(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 |