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