Saturday, September 8, 2012

Rubik Cube Animation Development in Android


This example shows how you can create Rubik’s cube in android.
Algorithm:
1.) Create a new project by File-> New -> Android Project name it RubikCubeAnimationExample.
2.) Create and write following into src/M4.java:
package com.example.RubikCubeAnimationExample;
public class M4 {
        public float[][] m = new float[4][4];
     
        public M4() {
        }

     
        public M4(M4 other) {
                for (int i = 0; i < 4; i++) {
                        for (int j = 0; j < 4; j++) {
                                m[i][j] = other.m[i][j];
                        }
                }            
        }
        public void multiply(GLVertex src, GLVertex dest) {
                dest.x = src.x * m[0][0] + src.y * m[1][0] + src.z * m[2][0] +m[3][0];
                dest.y = src.x * m[0][1] + src.y * m[1][1] + src.z * m[2][1] +m[3][1];
                dest.z = src.x * m[0][2] + src.y * m[1][2] + src.z * m[2][2] +m[3][2];
        }
     
        public M4 multiply(M4 other) {
                M4 result = new M4();
                float[][] m1 = m;
                float[][] m2 = other.m;
             
                for (int i = 0; i < 4; i++) {
                        for (int j = 0; j < 4; j++) {
                                result.m[i][j] = m1[i][0]*m2[0][j] +m1[i][1]*m2[1][j] + m1[i][2]*m2[2][j] + m1[i][3]*m2[3][j];
                        }
                }
             
                return result;
        }
     
        public void setIdentity() {
                for (int i = 0; i < 4; i++) {
                        for (int j = 0; j < 4; j++) {
                                m[i][j] = (== j ? 1f : 0f);
                        }
                }
        }
     
        @Override
        public String toString() {
                StringBuilder builder = new StringBuilder("[ ");
                for (int i = 0; i < 4; i++) {
                        for (int j = 0; j < 4; j++) {
                                builder.append(m[i][j]);
                                builder.append(" ");
                        }
                        if (< 2)
                                builder.append("\n  ");
                }
                builder.append(" ]");
                return builder.toString();
        }
}
3.) Create and write following into src/Layer.java:
package com.example.RubikCubeAnimationExample;
public class Layer {
     
        public Layer(int axis) {
                mAxis = axis;
                mTransform.setIdentity();
        }
     
        public void startAnimation() {
                for (int i = 0; i < mShapes.length; i++) {
                        GLShape shape = mShapes[i];
                        if (shape != null) {
                                shape.startAnimation();
                        }    
                }
        }
        public void endAnimation() {
                for (int i = 0; i < mShapes.length; i++) {
                        GLShape shape = mShapes[i];
                        if (shape != null) {
                                shape.endAnimation();
                        }    
                }
        }
     
        public void setAngle(float angle) {
                // normalize the angle
                float twopi = (float)Math.PI *2f;
                while (angle >= twopi) angle -= twopi;
                while (angle < 0f) angle += twopi;
//              mAngle = angle;
             
                float sin = (float)Math.sin(angle);
                float cos = (float)Math.cos(angle);
             
                float[][] m = mTransform.m;
                switch (mAxis) {
                        case kAxisX:
                                m[1][1] = cos;
                                m[1][2] = sin;
                                m[2][1] = -sin;
                                m[2][2] = cos;
                                m[0][0] = 1f;
                                m[0][1] = m[0][2] = m[1][0] = m[2][0] = 0f;
                                break;
                        case kAxisY:
                                m[0][0] = cos;
                                m[0][2] = sin;
                                m[2][0] = -sin;
                                m[2][2] = cos;
                                m[1][1] = 1f;
                                m[0][1] = m[1][0] = m[1][2] = m[2][1] = 0f;
                                break;
                        case kAxisZ:
                                m[0][0] = cos;
                                m[0][1] = sin;
                                m[1][0] = -sin;
                                m[1][1] = cos;
                                m[2][2] = 1f;
                                m[2][0] = m[2][1] = m[0][2] = m[1][2] = 0f;
                                break;
                }
             
                for (int i = 0; i < mShapes.length; i++) {
                        GLShape shape = mShapes[i];
                        if (shape != null) {
                                shape.animateTransform(mTransform);
                        }
                }
        }
     
        GLShape[] mShapes = new GLShape[9];
        M4 mTransform = new M4();
        int mAxis;
        static public final int kAxisX = 0;
        static public final int kAxisY = 1;
        static public final int kAxisZ = 2;  
}
4.) Create and write following into src/KubeRenderer.java:
package com.example.RubikCubeAnimationExample;
import android.opengl.GLSurfaceView;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;
class KubeRenderer implements GLSurfaceView.Renderer {
    public interface AnimationCallback {
        void animate();
    }
    public KubeRenderer(GLWorld world, AnimationCallback callback) {
        mWorld = world;
        mCallback = callback;
    }
    public void onDrawFrame(GL10 gl) {
         if (mCallback != null) {
             mCallback.animate();
         }
        gl.glClearColor(0.5f,0.5f,0.5f,1);
        gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
        gl.glMatrixMode(GL10.GL_MODELVIEW);
        gl.glLoadIdentity();
        gl.glTranslatef(0, 0, -3.0f);
        gl.glScalef(0.5f, 0.5f, 0.5f);
        gl.glRotatef(mAngle,        0, 1, 0);
        gl.glRotatef(mAngle*0.25f,  1, 0, 0);
        gl.glColor4f(0.7f, 0.7f, 0.7f, 1.0f);
        gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
        gl.glEnableClientState(GL10.GL_COLOR_ARRAY);
        gl.glEnable(GL10.GL_CULL_FACE);
        gl.glShadeModel(GL10.GL_SMOOTH);
        gl.glEnable(GL10.GL_DEPTH_TEST);
        mWorld.draw(gl);
    }
    public void onSurfaceChanged(GL10 gl, int width, int height) {
        gl.glViewport(0, 0, width, height);
        float ratio = (float)width / height;
        gl.glMatrixMode(GL10.GL_PROJECTION);
        gl.glLoadIdentity();
        gl.glFrustumf(-ratio, ratio, -1, 1, 2, 12);
        gl.glDisable(GL10.GL_DITHER);
        gl.glActiveTexture(GL10.GL_TEXTURE0);
    }
    public void onSurfaceCreated(GL10 gl, EGLConfig config) {
    }
    public void setAngle(float angle) {
        mAngle = angle;
    }
    public float getAngle() {
        return mAngle;
    }
    private GLWorld mWorld;
    private AnimationCallback mCallback;
    private float mAngle;
}
5.) Create and write following into src/GLWorld.java:
package com.example.RubikCubeAnimationExample;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.IntBuffer;
import java.nio.ShortBuffer;
import java.util.Iterator;
import java.util.ArrayList;
import javax.microedition.khronos.opengles.GL10;
public class GLWorld {
        public void addShape(GLShape shape) {
                mShapeList.add(shape);
                mIndexCount += shape.getIndexCount();
        }
     
        public void generate() {             
            ByteBuffer bb = ByteBuffer.allocateDirect(mVertexList.size()*4*4);
            bb.order(ByteOrder.nativeOrder());
                mColorBuffer = bb.asIntBuffer();
            bb = ByteBuffer.allocateDirect(mVertexList.size()*4*3);
            bb.order(ByteOrder.nativeOrder());
            mVertexBuffer = bb.asIntBuffer();
            bb = ByteBuffer.allocateDirect(mIndexCount*2);
            bb.order(ByteOrder.nativeOrder());
            mIndexBuffer = bb.asShortBuffer();
                Iterator<GLVertex> iter2 = mVertexList.iterator();
                while (iter2.hasNext()) {
                        GLVertex vertex = iter2.next();
                        vertex.put(mVertexBuffer, mColorBuffer);
                }
                Iterator<GLShape> iter3 = mShapeList.iterator();
                while (iter3.hasNext()) {
                        GLShape shape = iter3.next();
                        shape.putIndices(mIndexBuffer);
                }
        }
     
        public GLVertex addVertex(float x, float y, float z) {
                GLVertex vertex = new GLVertex(x, y, z, mVertexList.size());
                mVertexList.add(vertex);
                return vertex;
        }
     
        public void transformVertex(GLVertex vertex, M4 transform) {
                vertex.update(mVertexBuffer, transform);
        }
        int count = 0;
    public void draw(GL10 gl)
    {
                mColorBuffer.position(0);
                mVertexBuffer.position(0);
                mIndexBuffer.position(0);
                gl.glFrontFace(GL10.GL_CW);
        gl.glShadeModel(GL10.GL_FLAT);
        gl.glVertexPointer(3, GL10.GL_FIXED, 0, mVertexBuffer);
        gl.glColorPointer(4, GL10.GL_FIXED, 0, mColorBuffer);
        gl.glDrawElements(GL10.GL_TRIANGLES, mIndexCount, GL10.GL_UNSIGNED_SHORT, mIndexBuffer);
        count++;
    }

    static public float toFloat(int x) {
        return x/65536.0f;
    }
        private ArrayList<GLShape>      mShapeList = new ArrayList<GLShape>();
        private ArrayList<GLVertex>     mVertexList = new ArrayList<GLVertex>();
     
        private int mIndexCount = 0;
    private IntBuffer   mVertexBuffer;
    private IntBuffer   mColorBuffer;
    private ShortBuffer mIndexBuffer;
}
6.) Create and write following into src/GLVertex.java:
package com.example.RubikCubeAnimationExample;
import java.nio.IntBuffer;
public class GLVertex {
    public float x;
    public float y;
    public float z;
    final short index; // index in vertex table
    GLColor color;
    GLVertex() {
        this.x = 0;
        this.y = 0;
        this.z = 0;
        this.index = -1;
    }
    GLVertex(float x, float y, float z, int index) {
        this.x = x;
        this.y = y;
        this.z = z;
        this.index = (short)index;
    }
    @Override
    public boolean equals(Object other) {
        if (other instanceof GLVertex) {
            GLVertex v = (GLVertex)other;
            return (== v.x && y == v.y && z == v.z);
        }
        return false;
    }
    static public int toFixed(float x) {
        return (int)(* 65536.0f);
    }
    public void put(IntBuffer vertexBuffer, IntBuffer colorBuffer) {
        vertexBuffer.put(toFixed(x));
        vertexBuffer.put(toFixed(y));
        vertexBuffer.put(toFixed(z));
        if (color == null) {
            colorBuffer.put(0);
            colorBuffer.put(0);
            colorBuffer.put(0);
            colorBuffer.put(0);
        } else {
            colorBuffer.put(color.red);
            colorBuffer.put(color.green);
            colorBuffer.put(color.blue);
            colorBuffer.put(color.alpha);
        }
    }
    public void update(IntBuffer vertexBuffer, M4 transform) {
        // skip to location of vertex in mVertex buffer
        vertexBuffer.position(index * 3);
        if (transform == null) {
            vertexBuffer.put(toFixed(x));
            vertexBuffer.put(toFixed(y));
            vertexBuffer.put(toFixed(z));
        } else {
            GLVertex temp = new GLVertex();
            transform.multiply(this, temp);
            vertexBuffer.put(toFixed(temp.x));
            vertexBuffer.put(toFixed(temp.y));
            vertexBuffer.put(toFixed(temp.z));
        }
    }
}
7.) Create and write following into src/GLShape.java:
package com.example.RubikCubeAnimationExample;
import java.nio.ShortBuffer;
import java.util.ArrayList;
import java.util.Iterator;
public class GLShape {
        public GLShape(GLWorld world) {
                mWorld = world;
        }
     
        public void addFace(GLFace face) {
                mFaceList.add(face);
        }
     
        public void setFaceColor(int face, GLColor color) {
                mFaceList.get(face).setColor(color);
        }
                     
        public void putIndices(ShortBuffer buffer) {
                Iterator<GLFace> iter = mFaceList.iterator();
                while (iter.hasNext()) {
                        GLFace face = iter.next();
                        face.putIndices(buffer);
                }            
        }
     
        public int getIndexCount() {
                int count = 0;
                Iterator<GLFace> iter = mFaceList.iterator();
                while (iter.hasNext()) {
                        GLFace face = iter.next();
                        count += face.getIndexCount();
                }            
                return count;
        }
        public GLVertex addVertex(float x, float y, float z) {
             
                // look for an existing GLVertex first
                Iterator<GLVertex> iter = mVertexList.iterator();
                while (iter.hasNext()) {
                        GLVertex vertex = iter.next();
                        if (vertex.x == x && vertex.y == y && vertex.z == z) {
                                return vertex;
                        }
                }
             
                // doesn’t exist, so create new vertex
                GLVertex vertex = mWorld.addVertex(x, y, z);
                mVertexList.add(vertex);
                return vertex;
        }
        public void animateTransform(M4 transform) {
                mAnimateTransform = transform;
             
                if (mTransform != null)
                        transform = mTransform.multiply(transform);
                Iterator<GLVertex> iter = mVertexList.iterator();
                while (iter.hasNext()) {
                        GLVertex vertex = iter.next();
                        mWorld.transformVertex(vertex, transform);
                }
        }
     
        public void startAnimation() {
        }
        public void endAnimation() {
                if (mTransform == null) {
                        mTransform = new M4(mAnimateTransform);
                } else {
                        mTransform = mTransform.multiply(mAnimateTransform);
                }
        }
        public M4                                               mTransform;
        public M4                                               mAnimateTransform;
        protected ArrayList<GLFace>             mFaceList = newArrayList<GLFace>();
        protected ArrayList<GLVertex>   mVertexList = new ArrayList<GLVertex>();
        protected ArrayList<Integer>    mIndexList = new ArrayList<Integer>(); // make more efficient?
        protected GLWorld mWorld;
}
8.) Create and write following into src/GLFace.java:
package com.example.RubikCubeAnimationExample;
import android.util.Log;
import java.nio.ShortBuffer;
import java.util.ArrayList;
public class GLFace {
        public GLFace() {
             
        }
     
        // for triangles
        public GLFace(GLVertex v1, GLVertex v2, GLVertex v3) {
                addVertex(v1);
                addVertex(v2);
                addVertex(v3);
        }    
        // for quadrilaterals
        public GLFace(GLVertex v1, GLVertex v2, GLVertex v3, GLVertex v4) {
                addVertex(v1);
                addVertex(v2);
                addVertex(v3);
                addVertex(v4);
        }
             
        public void addVertex(GLVertex v) {
                mVertexList.add(v);
        }
     
        // must be called after all vertices are added
        public void setColor(GLColor c) {
             
                int last = mVertexList.size() - 1;
                if (last < 2) {
                        Log.e("GLFace""not enough vertices in setColor()");
                } else {
                        GLVertex vertex = mVertexList.get(last);
                     
                        // only need to do this if the color has never been set
                        if (mColor == null) {
                                while (vertex.color != null) {
                                        mVertexList.add(0, vertex);
                                        mVertexList.remove(last + 1);
                                        vertex = mVertexList.get(last);
                                }
                        }
                     
                        vertex.color = c;
                }
                mColor = c;
        }
     
        public int getIndexCount() {
                return (mVertexList.size() - 2) * 3;
        }
     
        public void putIndices(ShortBuffer buffer) {
                int last = mVertexList.size() - 1;
                GLVertex v0 = mVertexList.get(0);
                GLVertex vn = mVertexList.get(last);
             
                // push triangles into the buffer
                for (int i = 1; i < last; i++) {
                        GLVertex v1 = mVertexList.get(i);
                        buffer.put(v0.index);
                        buffer.put(v1.index);
                        buffer.put(vn.index);
                        v0 = v1;
                }
        }
     
        private ArrayList<GLVertex> mVertexList = new ArrayList<GLVertex>();
        private GLColor mColor;
}
9.) Create and write following into src/GLColor.java:
package com.example.RubikCubeAnimationExample;
public class GLColor {
    public final int red;
    public final int green;
    public final int blue;
    public final int alpha;
    public GLColor(int red, int green, int blue, int alpha) {
        this.red = red;
        this.green = green;
        this.blue = blue;
        this.alpha = alpha;
    }
    public GLColor(int red, int green, int blue) {
        this.red = red;
        this.green = green;
        this.blue = blue;
        this.alpha = 0×10000;
    }
    @Override
    public boolean equals(Object other) {
        if (other instanceof GLColor) {
            GLColor color = (GLColor)other;
            return (red == color.red &&
                    green == color.green &&
                    blue == color.blue &&
                    alpha == color.alpha);
        }
        return false;
    }
}
10.) Create and write following into src/Cube.java:
package com.example.RubikCubeAnimationExample;
public class Cube extends GLShape {
        public Cube(GLWorld world, float left, float bottom, float back, floatright, float top, float front) {
                super(world);
        GLVertex leftBottomBack = addVertex(left, bottom, back);
       GLVertex rightBottomBack = addVertex(right, bottom, back);
        GLVertex leftTopBack = addVertex(left, top, back);
        GLVertex rightTopBack = addVertex(right, top, back);
        GLVertex leftBottomFront = addVertex(left, bottom, front);
        GLVertex rightBottomFront = addVertex(right, bottom, front);
        GLVertex leftTopFront = addVertex(left, top, front);
        GLVertex rightTopFront = addVertex(right, top, front);
        addFace(new GLFace(leftBottomBack, leftBottomFront, rightBottomFront, rightBottomBack));
        addFace(new GLFace(leftBottomFront, leftTopFront, rightTopFront, rightBottomFront));
        addFace(new GLFace(leftBottomBack, leftTopBack, leftTopFront, leftBottomFront));
        addFace(new GLFace(rightBottomBack, rightBottomFront, rightTopFront, rightTopBack));
        addFace(new GLFace(leftBottomBack, rightBottomBack, rightTopBack, leftTopBack));
        addFace(new GLFace(leftTopBack, rightTopBack, rightTopFront, leftTopFront));
             
        }
     
    public static final int kBottom = 0;
    public static final int kFront = 1;
    public static final int kLeft = 2;
    public static final int kRight = 3;
    public static final int kBack = 4;
    public static final int kTop = 5;
     
}
11.) Run for output.
Steps:
1.) Create a project named RubikCubeAnimationExample and set the information as stated in the image.
Build Target: Android 4.0
Application Name: RubikCubeAnimationExample
Package Name: com. example. RubikCubeAnimationExample
Activity Name: RubikCubeAnimationExampleActivity
Min SDK Version: 14
2.) Open RubikCubeAnimationExampleActivity.java file and write following code there:
package com.example.RubikCubeAnimationExample;
import java.util.Random;
import android.app.Activity;
import android.opengl.GLSurfaceView;
import android.os.Bundle;
import android.view.Window;
public class RubikCubeAnimationExampleActivity extends Activity implementsKubeRenderer.AnimationCallback {
    private GLWorld makeGLWorld()
    {
        GLWorld world = new GLWorld();
        int one = 0×10000;
        int half = 0×08000;
        GLColor red = new GLColor(one, 0, 0);
        GLColor green = new GLColor(0, one, 0);
        GLColor blue = new GLColor(0, 0, one);
        GLColor yellow = new GLColor(one, one, 0);
        GLColor orange = new GLColor(one, half, 0);
        GLColor white = new GLColor(one, one, one);
        GLColor black = new GLColor(0, 0, 0);
        float c0 = -1.0f;
        float c1 = -0.38f;
        float c2 = -0.32f;
        float c3 = 0.32f;
        float c4 = 0.38f;
        float c5 = 1.0f;
        // top back, left to right
        mCubes[0]  = new Cube(world, c0, c4, c0, c1, c5, c1);
        mCubes[1]  = new Cube(world, c2, c4, c0, c3, c5, c1);
        mCubes[2]  = new Cube(world, c4, c4, c0, c5, c5, c1);
        // top middle, left to right
        mCubes[3]  = new Cube(world, c0, c4, c2, c1, c5, c3);
        mCubes[4]  = new Cube(world, c2, c4, c2, c3, c5, c3);
        mCubes[5]  = new Cube(world, c4, c4, c2, c5, c5, c3);
        // top front, left to right
        mCubes[6]  = new Cube(world, c0, c4, c4, c1, c5, c5);
        mCubes[7]  = new Cube(world, c2, c4, c4, c3, c5, c5);
        mCubes[8]  = new Cube(world, c4, c4, c4, c5, c5, c5);
        // middle back, left to right
        mCubes[9]  = new Cube(world, c0, c2, c0, c1, c3, c1);
        mCubes[10] = new Cube(world, c2, c2, c0, c3, c3, c1);
        mCubes[11] = new Cube(world, c4, c2, c0, c5, c3, c1);
        // middle middle, left to right
        mCubes[12] = new Cube(world, c0, c2, c2, c1, c3, c3);
        mCubes[13] = null;
        mCubes[14] = new Cube(world, c4, c2, c2, c5, c3, c3);
        // middle front, left to right
        mCubes[15] = new Cube(world, c0, c2, c4, c1, c3, c5);
        mCubes[16] = new Cube(world, c2, c2, c4, c3, c3, c5);
        mCubes[17] = new Cube(world, c4, c2, c4, c5, c3, c5);
        // bottom back, left to right
        mCubes[18] = new Cube(world, c0, c0, c0, c1, c1, c1);
        mCubes[19] = new Cube(world, c2, c0, c0, c3, c1, c1);
        mCubes[20] = new Cube(world, c4, c0, c0, c5, c1, c1);
        // bottom middle, left to right
        mCubes[21] = new Cube(world, c0, c0, c2, c1, c1, c3);
        mCubes[22] = new Cube(world, c2, c0, c2, c3, c1, c3);
        mCubes[23] = new Cube(world, c4, c0, c2, c5, c1, c3);
        // bottom front, left to right
        mCubes[24] = new Cube(world, c0, c0, c4, c1, c1, c5);
        mCubes[25] = new Cube(world, c2, c0, c4, c3, c1, c5);
        mCubes[26] = new Cube(world, c4, c0, c4, c5, c1, c5);
        // paint the sides
        int i, j;
        // set all faces black by default
        for (= 0; i < 27; i++) {
            Cube cube = mCubes[i];
            if (cube != null) {
                for (= 0; j < 6; j++)
                    cube.setFaceColor(j, black);
            }
        }
        // paint top
        for (= 0; i < 9; i++)
            mCubes[i].setFaceColor(Cube.kTop, orange);
        // paint bottom
        for (= 18; i < 27; i++)
            mCubes[i].setFaceColor(Cube.kBottom, red);
        // paint left
        for (= 0; i < 27; i += 3)
            mCubes[i].setFaceColor(Cube.kLeft, yellow);
        // paint right
        for (= 2; i < 27; i += 3)
            mCubes[i].setFaceColor(Cube.kRight, white);
        // paint back
        for (= 0; i < 27; i += 9)
            for (= 0; j < 3; j++)
                mCubes[+ j].setFaceColor(Cube.kBack, blue);
        // paint front
        for (= 6; i < 27; i += 9)
            for (= 0; j < 3; j++)
                mCubes[+ j].setFaceColor(Cube.kFront, green);
        for (= 0; i < 27; i++)
            if (mCubes[i] != null)
                world.addShape(mCubes[i]);
        // initialize our permutation to solved position
        mPermutation = new int[27];
        for (= 0; i < mPermutation.length; i++)
            mPermutation[i] = i;
        createLayers();
        updateLayers();
        world.generate();
        return world;
    }
    private void createLayers() {
        mLayers[kUp] = new Layer(Layer.kAxisY);
        mLayers[kDown] = new Layer(Layer.kAxisY);
        mLayers[kLeft] = new Layer(Layer.kAxisX);
        mLayers[kRight] = new Layer(Layer.kAxisX);
        mLayers[kFront] = new Layer(Layer.kAxisZ);
        mLayers[kBack] = new Layer(Layer.kAxisZ);
        mLayers[kMiddle] = new Layer(Layer.kAxisX);
        mLayers[kEquator] = new Layer(Layer.kAxisY);
        mLayers[kSide] = new Layer(Layer.kAxisZ);
    }
    private void updateLayers() {
        Layer layer;
        GLShape[] shapes;
        int i, j, k;
        // up layer
        layer = mLayers[kUp];
        shapes = layer.mShapes;
        for (= 0; i < 9; i++)
            shapes[i] = mCubes[mPermutation[i]];
        // down layer
        layer = mLayers[kDown];
        shapes = layer.mShapes;
        for (= 18, k = 0; i < 27; i++)
            shapes[k++] = mCubes[mPermutation[i]];
        // left layer
        layer = mLayers[kLeft];
        shapes = layer.mShapes;
        for (= 0, k = 0; i < 27; i += 9)
            for (= 0; j < 9; j += 3)
                shapes[k++] = mCubes[mPermutation[+ j]];
        // right layer
        layer = mLayers[kRight];
        shapes = layer.mShapes;
        for (= 2, k = 0; i < 27; i += 9)
            for (= 0; j < 9; j += 3)
                shapes[k++] = mCubes[mPermutation[+ j]];
        // front layer
        layer = mLayers[kFront];
        shapes = layer.mShapes;
        for (= 6, k = 0; i < 27; i += 9)
            for (= 0; j < 3; j++)
                shapes[k++] = mCubes[mPermutation[+ j]];
        // back layer
        layer = mLayers[kBack];
        shapes = layer.mShapes;
        for (= 0, k = 0; i < 27; i += 9)
            for (= 0; j < 3; j++)
                shapes[k++] = mCubes[mPermutation[+ j]];
        // middle layer
        layer = mLayers[kMiddle];
        shapes = layer.mShapes;
        for (= 1, k = 0; i < 27; i += 9)
            for (= 0; j < 9; j += 3)
                shapes[k++] = mCubes[mPermutation[+ j]];
        // equator layer
        layer = mLayers[kEquator];
        shapes = layer.mShapes;
        for (= 9, k = 0; i < 18; i++)
            shapes[k++] = mCubes[mPermutation[i]];
        // side layer
        layer = mLayers[kSide];
        shapes = layer.mShapes;
        for (= 3, k = 0; i < 27; i += 9)
            for (= 0; j < 3; j++)
                shapes[k++] = mCubes[mPermutation[+ j]];
    }
    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        // We don’t need a title either.
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        mView = new GLSurfaceView(getApplication());
        mRenderer = new KubeRenderer(makeGLWorld()this);
        mView.setRenderer(mRenderer);
        setContentView(mView);
    }
    @Override
    protected void onResume()
    {
        super.onResume();
        mView.onResume();
    }
    @Override
    protected void onPause()
    {
        super.onPause();
        mView.onPause();
    }
    public void animate() {
        // change our angle of view
        mRenderer.setAngle(mRenderer.getAngle() + 1.2f);
        if (mCurrentLayer == null) {
            int layerID = mRandom.nextInt(9);
            mCurrentLayer = mLayers[layerID];
            mCurrentLayerPermutation = mLayerPermutations[layerID];
            mCurrentLayer.startAnimation();
            boolean direction = mRandom.nextBoolean();
            int count = mRandom.nextInt(3) + 1;
            count = 1;
            direction = false;
            mCurrentAngle = 0;
             if (direction) {
                mAngleIncrement = (float)Math.PI / 50;
                   mEndAngle = mCurrentAngle + ((float)Math.PI * count) / 2f;
               } else {
                mAngleIncrement = -(float)Math.PI / 50;
                   mEndAngle = mCurrentAngle - ((float)Math.PI * count) / 2f;
            }
        }
         mCurrentAngle += mAngleIncrement;
         if ((mAngleIncrement > 0f && mCurrentAngle >= mEndAngle) ||
                 (mAngleIncrement < 0f && mCurrentAngle <= mEndAngle)) {
             mCurrentLayer.setAngle(mEndAngle);
             mCurrentLayer.endAnimation();
             mCurrentLayer = null;
             // adjust mPermutation based on the completed layer rotation
             int[] newPermutation = new int[27];
             for (int i = 0; i < 27; i++) {
                newPermutation[i] = mPermutation[mCurrentLayerPermutation[i]];
              }
             mPermutation = newPermutation;
             updateLayers();
         } else {
             mCurrentLayer.setAngle(mCurrentAngle);
         }
    }
    GLSurfaceView mView;
    KubeRenderer mRenderer;
    Cube[] mCubes = new Cube[27];
    // a Layer for each possible move
    Layer[] mLayers = new Layer[9];
    // permutations corresponding to a pi/2 rotation of each layer about its axis
    static int[][] mLayerPermutations = {
            // permutation for UP layer
            { 2581470369101112131415161718,1920212223242526 },
            // permutation for DOWN layer
            { 0123456789101112131415161720,2326192225182124 },
            // permutation for LEFT layer
            { 61215452478310111213142116170,192092223182526 },
            // permutation for RIGHT layer
            { 01834176726910512131415162318,192212211242520 },
            // permutation for FRONT layer
            { 01234524156910111213142516718,192021222326178 },
            // permutation for BACK layer
            { 18903456781910112131415161720,112212223242526 },
            // permutation for MIDDLE layer
            { 07231656258941112131415221718,120211023241926 },
            // permutation for EQUATOR layer
            { 0123456781114171013169121518,1920212223242526 },
            // permutation for SIDE layer
            { 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 }
    };
    // current permutation of starting position
    int[] mPermutation;
    // for random cube movements
    Random mRandom = new Random(System.currentTimeMillis());
    // currently turning layer
    Layer mCurrentLayer = null;
    // current and final angle for current Layer animation
    float mCurrentAngle, mEndAngle;
    // amount to increment angle
    float mAngleIncrement;
    int[] mCurrentLayerPermutation;
    // names for our 9 layers (based on notation from http://www.cubefreak.net/notation.html)
    static final int kUp = 0;
    static final int kDown = 1;
    static final int kLeft = 2;
    static final int kRight = 3;
    static final int kFront = 4;
    static final int kBack = 5;
    static final int kMiddle = 6;
    static final int kEquator = 7;
    static final int kSide = 8;
}
3.) Compile and build the project.
Output

No comments:

Post a Comment