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 |