1 /*
2  * Copyright (C) 2008 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.example.android.apis.graphics.kube;
18 
19 import android.app.Activity;
20 import android.os.Bundle;
21 import android.view.Window;
22 
23 import android.opengl.GLSurfaceView;
24 
25 import java.util.Random;
26 
27 public class Kube extends Activity implements KubeRenderer.AnimationCallback {
28 
makeGLWorld()29     private GLWorld makeGLWorld()
30     {
31         GLWorld world = new GLWorld();
32 
33         int one = 0x10000;
34         int half = 0x08000;
35         GLColor red = new GLColor(one, 0, 0);
36         GLColor green = new GLColor(0, one, 0);
37         GLColor blue = new GLColor(0, 0, one);
38         GLColor yellow = new GLColor(one, one, 0);
39         GLColor orange = new GLColor(one, half, 0);
40         GLColor white = new GLColor(one, one, one);
41         GLColor black = new GLColor(0, 0, 0);
42 
43         // coordinates for our cubes
44         float c0 = -1.0f;
45         float c1 = -0.38f;
46         float c2 = -0.32f;
47         float c3 = 0.32f;
48         float c4 = 0.38f;
49         float c5 = 1.0f;
50 
51         // top back, left to right
52         mCubes[0]  = new Cube(world, c0, c4, c0, c1, c5, c1);
53         mCubes[1]  = new Cube(world, c2, c4, c0, c3, c5, c1);
54         mCubes[2]  = new Cube(world, c4, c4, c0, c5, c5, c1);
55         // top middle, left to right
56         mCubes[3]  = new Cube(world, c0, c4, c2, c1, c5, c3);
57         mCubes[4]  = new Cube(world, c2, c4, c2, c3, c5, c3);
58         mCubes[5]  = new Cube(world, c4, c4, c2, c5, c5, c3);
59         // top front, left to right
60         mCubes[6]  = new Cube(world, c0, c4, c4, c1, c5, c5);
61         mCubes[7]  = new Cube(world, c2, c4, c4, c3, c5, c5);
62         mCubes[8]  = new Cube(world, c4, c4, c4, c5, c5, c5);
63         // middle back, left to right
64         mCubes[9]  = new Cube(world, c0, c2, c0, c1, c3, c1);
65         mCubes[10] = new Cube(world, c2, c2, c0, c3, c3, c1);
66         mCubes[11] = new Cube(world, c4, c2, c0, c5, c3, c1);
67         // middle middle, left to right
68         mCubes[12] = new Cube(world, c0, c2, c2, c1, c3, c3);
69         mCubes[13] = null;
70         mCubes[14] = new Cube(world, c4, c2, c2, c5, c3, c3);
71         // middle front, left to right
72         mCubes[15] = new Cube(world, c0, c2, c4, c1, c3, c5);
73         mCubes[16] = new Cube(world, c2, c2, c4, c3, c3, c5);
74         mCubes[17] = new Cube(world, c4, c2, c4, c5, c3, c5);
75         // bottom back, left to right
76         mCubes[18] = new Cube(world, c0, c0, c0, c1, c1, c1);
77         mCubes[19] = new Cube(world, c2, c0, c0, c3, c1, c1);
78         mCubes[20] = new Cube(world, c4, c0, c0, c5, c1, c1);
79         // bottom middle, left to right
80         mCubes[21] = new Cube(world, c0, c0, c2, c1, c1, c3);
81         mCubes[22] = new Cube(world, c2, c0, c2, c3, c1, c3);
82         mCubes[23] = new Cube(world, c4, c0, c2, c5, c1, c3);
83         // bottom front, left to right
84         mCubes[24] = new Cube(world, c0, c0, c4, c1, c1, c5);
85         mCubes[25] = new Cube(world, c2, c0, c4, c3, c1, c5);
86         mCubes[26] = new Cube(world, c4, c0, c4, c5, c1, c5);
87 
88         // paint the sides
89         int i, j;
90         // set all faces black by default
91         for (i = 0; i < 27; i++) {
92             Cube cube = mCubes[i];
93             if (cube != null) {
94                 for (j = 0; j < 6; j++)
95                     cube.setFaceColor(j, black);
96             }
97         }
98 
99         // paint top
100         for (i = 0; i < 9; i++)
101             mCubes[i].setFaceColor(Cube.kTop, orange);
102         // paint bottom
103         for (i = 18; i < 27; i++)
104             mCubes[i].setFaceColor(Cube.kBottom, red);
105         // paint left
106         for (i = 0; i < 27; i += 3)
107             mCubes[i].setFaceColor(Cube.kLeft, yellow);
108         // paint right
109         for (i = 2; i < 27; i += 3)
110             mCubes[i].setFaceColor(Cube.kRight, white);
111         // paint back
112         for (i = 0; i < 27; i += 9)
113             for (j = 0; j < 3; j++)
114                 mCubes[i + j].setFaceColor(Cube.kBack, blue);
115         // paint front
116         for (i = 6; i < 27; i += 9)
117             for (j = 0; j < 3; j++)
118                 mCubes[i + j].setFaceColor(Cube.kFront, green);
119 
120         for (i = 0; i < 27; i++)
121             if (mCubes[i] != null)
122                 world.addShape(mCubes[i]);
123 
124         // initialize our permutation to solved position
125         mPermutation = new int[27];
126         for (i = 0; i < mPermutation.length; i++)
127             mPermutation[i] = i;
128 
129         createLayers();
130         updateLayers();
131 
132         world.generate();
133 
134         return world;
135     }
136 
createLayers()137     private void createLayers() {
138         mLayers[kUp] = new Layer(Layer.kAxisY);
139         mLayers[kDown] = new Layer(Layer.kAxisY);
140         mLayers[kLeft] = new Layer(Layer.kAxisX);
141         mLayers[kRight] = new Layer(Layer.kAxisX);
142         mLayers[kFront] = new Layer(Layer.kAxisZ);
143         mLayers[kBack] = new Layer(Layer.kAxisZ);
144         mLayers[kMiddle] = new Layer(Layer.kAxisX);
145         mLayers[kEquator] = new Layer(Layer.kAxisY);
146         mLayers[kSide] = new Layer(Layer.kAxisZ);
147     }
148 
updateLayers()149     private void updateLayers() {
150         Layer layer;
151         GLShape[] shapes;
152         int i, j, k;
153 
154         // up layer
155         layer = mLayers[kUp];
156         shapes = layer.mShapes;
157         for (i = 0; i < 9; i++)
158             shapes[i] = mCubes[mPermutation[i]];
159 
160         // down layer
161         layer = mLayers[kDown];
162         shapes = layer.mShapes;
163         for (i = 18, k = 0; i < 27; i++)
164             shapes[k++] = mCubes[mPermutation[i]];
165 
166         // left layer
167         layer = mLayers[kLeft];
168         shapes = layer.mShapes;
169         for (i = 0, k = 0; i < 27; i += 9)
170             for (j = 0; j < 9; j += 3)
171                 shapes[k++] = mCubes[mPermutation[i + j]];
172 
173         // right layer
174         layer = mLayers[kRight];
175         shapes = layer.mShapes;
176         for (i = 2, k = 0; i < 27; i += 9)
177             for (j = 0; j < 9; j += 3)
178                 shapes[k++] = mCubes[mPermutation[i + j]];
179 
180         // front layer
181         layer = mLayers[kFront];
182         shapes = layer.mShapes;
183         for (i = 6, k = 0; i < 27; i += 9)
184             for (j = 0; j < 3; j++)
185                 shapes[k++] = mCubes[mPermutation[i + j]];
186 
187         // back layer
188         layer = mLayers[kBack];
189         shapes = layer.mShapes;
190         for (i = 0, k = 0; i < 27; i += 9)
191             for (j = 0; j < 3; j++)
192                 shapes[k++] = mCubes[mPermutation[i + j]];
193 
194         // middle layer
195         layer = mLayers[kMiddle];
196         shapes = layer.mShapes;
197         for (i = 1, k = 0; i < 27; i += 9)
198             for (j = 0; j < 9; j += 3)
199                 shapes[k++] = mCubes[mPermutation[i + j]];
200 
201         // equator layer
202         layer = mLayers[kEquator];
203         shapes = layer.mShapes;
204         for (i = 9, k = 0; i < 18; i++)
205             shapes[k++] = mCubes[mPermutation[i]];
206 
207         // side layer
208         layer = mLayers[kSide];
209         shapes = layer.mShapes;
210         for (i = 3, k = 0; i < 27; i += 9)
211             for (j = 0; j < 3; j++)
212                 shapes[k++] = mCubes[mPermutation[i + j]];
213     }
214 
215     @Override
onCreate(Bundle savedInstanceState)216     protected void onCreate(Bundle savedInstanceState)
217     {
218         super.onCreate(savedInstanceState);
219 
220         // We don't need a title either.
221         requestWindowFeature(Window.FEATURE_NO_TITLE);
222 
223         mView = new GLSurfaceView(getApplication());
224         mRenderer = new KubeRenderer(makeGLWorld(), this);
225         mView.setRenderer(mRenderer);
226         setContentView(mView);
227     }
228 
229     @Override
onResume()230     protected void onResume()
231     {
232         super.onResume();
233         mView.onResume();
234     }
235 
236     @Override
onPause()237     protected void onPause()
238     {
239         super.onPause();
240         mView.onPause();
241     }
242 
animate()243     public void animate() {
244         // change our angle of view
245         mRenderer.setAngle(mRenderer.getAngle() + 1.2f);
246 
247         if (mCurrentLayer == null) {
248             int layerID = mRandom.nextInt(9);
249             mCurrentLayer = mLayers[layerID];
250             mCurrentLayerPermutation = mLayerPermutations[layerID];
251             mCurrentLayer.startAnimation();
252             boolean direction = mRandom.nextBoolean();
253             int count = mRandom.nextInt(3) + 1;
254 
255             count = 1;
256             direction = false;
257             mCurrentAngle = 0;
258              if (direction) {
259                 mAngleIncrement = (float)Math.PI / 50;
260                    mEndAngle = mCurrentAngle + ((float)Math.PI * count) / 2f;
261                } else {
262                 mAngleIncrement = -(float)Math.PI / 50;
263                    mEndAngle = mCurrentAngle - ((float)Math.PI * count) / 2f;
264             }
265         }
266 
267          mCurrentAngle += mAngleIncrement;
268 
269          if ((mAngleIncrement > 0f && mCurrentAngle >= mEndAngle) ||
270                  (mAngleIncrement < 0f && mCurrentAngle <= mEndAngle)) {
271              mCurrentLayer.setAngle(mEndAngle);
272              mCurrentLayer.endAnimation();
273              mCurrentLayer = null;
274 
275              // adjust mPermutation based on the completed layer rotation
276              int[] newPermutation = new int[27];
277              for (int i = 0; i < 27; i++) {
278                 newPermutation[i] = mPermutation[mCurrentLayerPermutation[i]];
279  //    			newPermutation[i] = mCurrentLayerPermutation[mPermutation[i]];
280              }
281              mPermutation = newPermutation;
282              updateLayers();
283 
284          } else {
285              mCurrentLayer.setAngle(mCurrentAngle);
286          }
287     }
288 
289     GLSurfaceView mView;
290     KubeRenderer mRenderer;
291     Cube[] mCubes = new Cube[27];
292     // a Layer for each possible move
293     Layer[] mLayers = new Layer[9];
294     // permutations corresponding to a pi/2 rotation of each layer about its axis
295     static int[][] mLayerPermutations = {
296             // permutation for UP layer
297             { 2, 5, 8, 1, 4, 7, 0, 3, 6, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26 },
298             // permutation for DOWN layer
299             { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 20, 23, 26, 19, 22, 25, 18, 21, 24 },
300             // permutation for LEFT layer
301             { 6, 1, 2, 15, 4, 5, 24, 7, 8, 3, 10, 11, 12, 13, 14, 21, 16, 17, 0, 19, 20, 9, 22, 23, 18, 25, 26 },
302             // permutation for RIGHT layer
303             { 0, 1, 8, 3, 4, 17, 6, 7, 26, 9, 10, 5, 12, 13, 14, 15, 16, 23, 18, 19, 2, 21, 22, 11, 24, 25, 20 },
304             // permutation for FRONT layer
305             { 0, 1, 2, 3, 4, 5, 24, 15, 6, 9, 10, 11, 12, 13, 14, 25, 16, 7, 18, 19, 20, 21, 22, 23, 26, 17, 8 },
306             // permutation for BACK layer
307             { 18, 9, 0, 3, 4, 5, 6, 7, 8, 19, 10, 1, 12, 13, 14, 15, 16, 17, 20, 11, 2, 21, 22, 23, 24, 25, 26 },
308             // permutation for MIDDLE layer
309             { 0, 7, 2, 3, 16, 5, 6, 25, 8, 9, 4, 11, 12, 13, 14, 15, 22, 17, 18, 1, 20, 21, 10, 23, 24, 19, 26 },
310             // permutation for EQUATOR layer
311             { 0, 1, 2, 3, 4, 5, 6, 7, 8, 11, 14, 17, 10, 13, 16, 9, 12, 15, 18, 19, 20, 21, 22, 23, 24, 25, 26 },
312             // permutation for SIDE layer
313             { 0, 1, 2, 21, 12, 3, 6, 7, 8, 9, 10, 11, 22, 13, 4, 15, 16, 17, 18, 19, 20, 23, 14, 5, 24, 25, 26 }
314     };
315 
316 
317 
318     // current permutation of starting position
319     int[] mPermutation;
320 
321     // for random cube movements
322     Random mRandom = new Random(System.currentTimeMillis());
323     // currently turning layer
324     Layer mCurrentLayer = null;
325     // current and final angle for current Layer animation
326     float mCurrentAngle, mEndAngle;
327     // amount to increment angle
328     float mAngleIncrement;
329     int[] mCurrentLayerPermutation;
330 
331     // names for our 9 layers (based on notation from http://www.cubefreak.net/notation.html)
332     static final int kUp = 0;
333     static final int kDown = 1;
334     static final int kLeft = 2;
335     static final int kRight = 3;
336     static final int kFront = 4;
337     static final int kBack = 5;
338     static final int kMiddle = 6;
339     static final int kEquator = 7;
340     static final int kSide = 8;
341 
342 }
343