Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(638)

Side by Side Diff: remoting/android/java/src/org/chromium/chromoting/cardboard/Photosphere.java

Issue 2252123002: [Remoting Android] Remove Cardboard Code (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Reviewer's Feedback - Removed unused const and strings Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
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
3 // found in the LICENSE file.
4
5 package org.chromium.chromoting.cardboard;
6
7 import static org.chromium.chromoting.cardboard.CardboardUtil.makeFloatBuffer;
8 import static org.chromium.chromoting.cardboard.CardboardUtil.makeShortBuffer;
9
10 import android.app.Activity;
11 import android.graphics.Bitmap;
12 import android.graphics.BitmapFactory;
13 import android.opengl.GLES20;
14
15 import com.google.vrtoolkit.cardboard.Eye;
16
17 import org.chromium.base.Log;
18 import org.chromium.chromoting.ChromotingDownloadManager;
19
20 import java.nio.FloatBuffer;
21 import java.nio.ShortBuffer;
22
23 /**
24 * Cardboard Activity photosphere, which is used to draw the activity environmen t.
25 */
26 public class Photosphere {
27 private static final String TAG = "Cardboard";
28
29 private static final String VERTEX_SHADER =
30 "uniform mat4 u_CombinedMatrix;"
31 + "attribute vec4 a_Position;"
32 + "attribute vec2 a_TexCoordinate;"
33 + "varying vec2 v_TexCoordinate;"
34 + "void main() {"
35 + " v_TexCoordinate = a_TexCoordinate;"
36 + " gl_Position = u_CombinedMatrix * a_Position;"
37 + "}";
38
39 private static final String FRAGMENT_SHADER =
40 "precision mediump float;"
41 + "uniform sampler2D u_Texture;"
42 + "varying vec2 v_TexCoordinate;"
43 + "void main() {"
44 + " gl_FragColor = texture2D(u_Texture, v_TexCoordinate);"
45 + "}";
46
47 private int mVertexShaderHandle;
48 private int mFragmentShaderHandle;
49 private int mProgramHandle;
50 private int mCombinedMatrixHandle;
51 private int mPositionHandle;
52 private int mLeftEyeTextureDataHandle;
53 private int mRightEyeTextureDataHandle;
54 private int mTextureCoordinateHandle;
55 private int mTextureUniformHandle;
56
57 private static final float RADIUS = 100.0f;
58
59 // Subdivision of the texture.
60 // Note: (COLUMS + 1) * (ROWS + 1), which is the number of vertices, should be within the
61 // range of short.
62 private static final int COLUMNS = 100;
63 private static final int ROWS = 50;
64
65 private static final int POSITION_DATA_SIZE = 3;
66 private static final int TEXTURE_COORDINATE_DATA_SIZE = 2;
67
68 // Number of drawing vertices needed to draw a rectangle surface.
69 private static final int NUM_DRAWING_VERTICES_PER_RECT = 6;
70
71 private static final int NUM_VERTICES = (ROWS + 1) * (COLUMNS + 1);
72
73 // Number of drawing vertices passed to glDrawElements().
74 private static final int NUM_DRAWING_VERTICES = ROWS * COLUMNS * NUM_DRAWING _VERTICES_PER_RECT;
75
76 // TODO(shichengfeng): Find a photosphere image and upload it.
77 private static final String IMAGE_URI =
78 "https://dl.google.com/chrome-remote-desktop/android-assets/photosph ere.jpg";
79 private static final String IMAGE_NAME = "photosphere";
80
81 private static final ShortBuffer INDICES_BUFFER = calculateIndicesBuffer();
82
83 // Maximum resolution for decoded image.
84 private static final int MAX_WIDTH = 4096;
85 private static final int MAX_HEIGHT = 4096;
86
87 private FloatBuffer mPositionBuffer;
88 private FloatBuffer mTextureCoordinatesBuffer;
89
90 private Activity mActivity;
91
92 private String mDownloadDirectory;
93
94 // Lock to allow multithreaded access to mDownloadDirectory.
95 private final Object mDownloadDirectoryLock = new Object();
96
97 // Flag to signal that the image is fully decoded and should be loaded
98 // into the OpenGL textures.
99 private boolean mLoadTexture;
100
101 // Lock to allow multithreaded access to mLoadTexture.
102 private final Object mLoadTextureLock = new Object();
103
104 ChromotingDownloadManager mDownloadManager;
105
106 public Photosphere(Activity activity) {
107 mActivity = activity;
108
109 calculatePosition();
110 calculateIndicesBuffer();
111
112 // Set handlers for eye point drawing.
113 mVertexShaderHandle =
114 ShaderHelper.compileShader(GLES20.GL_VERTEX_SHADER, VERTEX_SHADE R);
115 mFragmentShaderHandle =
116 ShaderHelper.compileShader(GLES20.GL_FRAGMENT_SHADER, FRAGMENT_S HADER);
117 mProgramHandle = ShaderHelper.createAndLinkProgram(mVertexShaderHandle,
118 mFragmentShaderHandle, new String[] {"a_Position", "u_CombinedMa trix",
119 "a_TexCoordinate", "u_Texture"});
120 mPositionHandle =
121 GLES20.glGetAttribLocation(mProgramHandle, "a_Position");
122 mCombinedMatrixHandle =
123 GLES20.glGetUniformLocation(mProgramHandle, "u_CombinedMatrix");
124 mTextureCoordinateHandle =
125 GLES20.glGetAttribLocation(mProgramHandle, "a_TexCoordinate");
126 mTextureUniformHandle =
127 GLES20.glGetUniformLocation(mProgramHandle, "u_TextureUnit");
128 mLeftEyeTextureDataHandle = TextureHelper.createTextureHandle();
129 mRightEyeTextureDataHandle = TextureHelper.createTextureHandle();
130
131 mActivity.runOnUiThread(new Runnable() {
132 public void run() {
133 // Download the phtosphere image.
134 mDownloadManager = new ChromotingDownloadManager(mActivity, IMAG E_NAME,
135 IMAGE_URI, new ChromotingDownloadManager.Callback() {
136 @Override
137 public void onBatchDownloadComplete() {
138 synchronized (mLoadTextureLock) {
139 mLoadTexture = true;
140 }
141 }
142 });
143 synchronized (mDownloadDirectoryLock) {
144 mDownloadDirectory = mDownloadManager.getDownloadDirectory() ;
145 }
146 mDownloadManager.download();
147 }
148 });
149 }
150
151 /**
152 * Set the texture for photosphere and clean temporary decoded image at the end.
153 * Only call this method when we have completely downloaded photosphere imag e.
154 */
155 public void maybeLoadTextureAndCleanImage() {
156 synchronized (mLoadTextureLock) {
157 if (!mLoadTexture) {
158 return;
159 }
160 mLoadTexture = false;
161 }
162
163 Bitmap image;
164 synchronized (mDownloadDirectoryLock) {
165 // This will only be executed when download finishes, which runs on main thread.
166 // On the main thread, we first initialize mDownloadDirectory and th en start download,
167 // so it is safe to use mDownloadDirectory here.
168 // First decode with inJustDecodeBounds = true to check dimensions.
169 final BitmapFactory.Options options = new BitmapFactory.Options();
170 options.inJustDecodeBounds = true;
171 BitmapFactory.decodeFile(mDownloadDirectory + "/" + IMAGE_NAME, opti ons);
172
173 calculateInSampleSize(options);
174
175 // Decode bitmap with inSampleSize set
176 options.inJustDecodeBounds = false;
177 image = BitmapFactory.decodeFile(mDownloadDirectory + "/" + IMAGE_NA ME, options);
178 }
179
180 if (image == null) {
181 Log.i(TAG, "Failed to decode image files.");
182 return;
183 }
184
185 Bitmap leftEyeImage = Bitmap.createBitmap(image, 0, 0, image.getWidth(),
186 image.getHeight() / 2);
187 TextureHelper.linkTexture(mLeftEyeTextureDataHandle, leftEyeImage);
188 leftEyeImage.recycle();
189 Bitmap rightEyeImage = Bitmap.createBitmap(image, 0, image.getHeight() / 2,
190 image.getWidth(), image.getHeight() / 2);
191 TextureHelper.linkTexture(mRightEyeTextureDataHandle, rightEyeImage);
192 rightEyeImage.recycle();
193
194 image.recycle();
195 }
196
197 public void draw(float[] combinedMatrix, int eyeType) {
198 GLES20.glUseProgram(mProgramHandle);
199
200 // Pass in model view project matrix.
201 GLES20.glUniformMatrix4fv(mCombinedMatrixHandle, 1, false, combinedMatri x, 0);
202
203 GLES20.glVertexAttribPointer(mPositionHandle, POSITION_DATA_SIZE, GLES20 .GL_FLOAT,
204 false, 0, mPositionBuffer);
205 GLES20.glEnableVertexAttribArray(mPositionHandle);
206
207 // Pass in texture coordinate.
208 GLES20.glVertexAttribPointer(mTextureCoordinateHandle, TEXTURE_COORDINAT E_DATA_SIZE,
209 GLES20.GL_FLOAT, false, 0, mTextureCoordinatesBuffer);
210 GLES20.glEnableVertexAttribArray(mTextureCoordinateHandle);
211
212 // Link texture data with texture unit.
213 GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
214 if (eyeType == Eye.Type.LEFT) {
215 GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mLeftEyeTextureDataHandle );
216 } else if (eyeType == Eye.Type.RIGHT) {
217 GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mRightEyeTextureDataHandl e);
218 }
219 GLES20.glUniform1i(mTextureUniformHandle, 0);
220
221 GLES20.glDrawElements(GLES20.GL_TRIANGLES, NUM_DRAWING_VERTICES, GLES20. GL_UNSIGNED_SHORT,
222 INDICES_BUFFER);
223
224 GLES20.glDisableVertexAttribArray(mPositionHandle);
225 GLES20.glDisableVertexAttribArray(mTextureCoordinateHandle);
226 }
227
228 /**
229 * Calculate the sphere position coordinates and texture coordinates.
230 */
231 private void calculatePosition() {
232 float[] vertexCoordinates = new float[NUM_VERTICES * POSITION_DATA_SIZE] ;
233 float[] textureCoordinates = new float[NUM_VERTICES * TEXTURE_COORDINATE _DATA_SIZE];
234
235 int vertexIndex = 0;
236 int textureCoordinateIndex = 0;
237 for (int row = 0; row <= ROWS; row++) {
238 for (int column = 0; column <= COLUMNS; column++) {
239 double theta = (ROWS / 2.0 - row) / (ROWS / 2.0) * Math.PI / 2;
240 double phi = 2 * Math.PI * column / COLUMNS;
241 float x = (float) (RADIUS * Math.cos(theta) * Math.cos(phi));
242 float y = (float) (RADIUS * Math.sin(theta));
243 float z = (float) (RADIUS * Math.cos(theta) * Math.sin(phi));
244
245 vertexCoordinates[vertexIndex++] = x;
246 vertexCoordinates[vertexIndex++] = y;
247 vertexCoordinates[vertexIndex++] = z;
248
249 textureCoordinates[textureCoordinateIndex++] = (float) column / COLUMNS;
250 textureCoordinates[textureCoordinateIndex++] = (float) row / ROW S;
251 }
252 }
253
254 mPositionBuffer = makeFloatBuffer(vertexCoordinates);
255 mTextureCoordinatesBuffer = makeFloatBuffer(textureCoordinates);
256 }
257
258 /**
259 * Calculate the drawing indices buffer.
260 */
261 private static ShortBuffer calculateIndicesBuffer() {
262 short[] indices = new short[NUM_DRAWING_VERTICES];
263 int currentIndex = 0;
264 for (int row = 0; row < ROWS; row++) {
265 for (int column = 0; column < COLUMNS; column++) {
266 int topLeft = row * (COLUMNS + 1) + column;
267 int topRight = topLeft + 1;
268 int bottomLeft = topLeft + (COLUMNS + 1);
269 int bottomRight = bottomLeft + 1;
270 indices[currentIndex++] = (short) topLeft;
271 indices[currentIndex++] = (short) bottomLeft;
272 indices[currentIndex++] = (short) topRight;
273 indices[currentIndex++] = (short) bottomLeft;
274 indices[currentIndex++] = (short) bottomRight;
275 indices[currentIndex++] = (short) topRight;
276 }
277 }
278 return makeShortBuffer(indices);
279 }
280
281 /**
282 * Clean up opengl data.
283 */
284 public void cleanup() {
285 GLES20.glDeleteShader(mVertexShaderHandle);
286 GLES20.glDeleteShader(mFragmentShaderHandle);
287 GLES20.glDeleteTextures(2, new int[] {mLeftEyeTextureDataHandle,
288 mRightEyeTextureDataHandle}, 0);
289
290 mActivity.runOnUiThread(new Runnable() {
291 public void run() {
292 mDownloadManager.close();
293 }
294 });
295 }
296
297 // Calculate InSampleSize, which is the number of pixels in either dimension that correspond
298 // to a single pixel in the decoded bitmap.
299 private static void calculateInSampleSize(BitmapFactory.Options options) {
300 // Raw height and width of image
301 int height = options.outHeight;
302 int width = options.outWidth;
303 int inSampleSize = 1;
304
305 while (height > MAX_HEIGHT || width > MAX_WIDTH) {
306 inSampleSize *= 2;
307 height /= 2;
308 width /= 2;
309 }
310
311 options.inSampleSize = inSampleSize;
312 }
313 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698