Home | History | Annotate | Download | only in kube
      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 
     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 
    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 
    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
    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
    230     protected void onResume()
    231     {
    232         super.onResume();
    233         mView.onResume();
    234     }
    235 
    236     @Override
    237     protected void onPause()
    238     {
    239         super.onPause();
    240         mView.onPause();
    241     }
    242 
    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