Revision 7ff38997
Added by Leszek Koltunski about 4 years ago
| src/main/java/org/distorted/helpers/ScrambleStateSquare1.java | ||
|---|---|---|
| 1 | 
    ///////////////////////////////////////////////////////////////////////////////////////////////////  | 
|
| 2 | 
    // Copyright 2021 Leszek Koltunski //  | 
|
| 3 | 
    // //  | 
|
| 4 | 
    // This file is part of Magic Cube. //  | 
|
| 5 | 
    // //  | 
|
| 6 | 
    // Magic Cube is free software: you can redistribute it and/or modify //  | 
|
| 7 | 
    // it under the terms of the GNU General Public License as published by //  | 
|
| 8 | 
    // the Free Software Foundation, either version 2 of the License, or //  | 
|
| 9 | 
    // (at your option) any later version. //  | 
|
| 10 | 
    // //  | 
|
| 11 | 
    // Magic Cube is distributed in the hope that it will be useful, //  | 
|
| 12 | 
    // but WITHOUT ANY WARRANTY; without even the implied warranty of //  | 
|
| 13 | 
    // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //  | 
|
| 14 | 
    // GNU General Public License for more details. //  | 
|
| 15 | 
    // //  | 
|
| 16 | 
    // You should have received a copy of the GNU General Public License //  | 
|
| 17 | 
    // along with Magic Cube. If not, see <http://www.gnu.org/licenses/>. //  | 
|
| 18 | 
    ///////////////////////////////////////////////////////////////////////////////////////////////////  | 
|
| 19 | 
     | 
|
| 20 | 
    package org.distorted.helpers;  | 
|
| 21 | 
     | 
|
| 22 | 
    import java.util.ArrayList;  | 
|
| 23 | 
    import java.util.Random;  | 
|
| 24 | 
     | 
|
| 25 | 
    ///////////////////////////////////////////////////////////////////////////////////////////////////  | 
|
| 26 | 
    // producer of the ScrambleStateGraph - but only for a single Twisty Puzzle, the 'Square-1'.  | 
|
| 27 | 
     | 
|
| 28 | 
    public class ScrambleStateSquare1  | 
|
| 29 | 
    {
   | 
|
| 30 | 
    private static final int INVALID_MOVE = -1;  | 
|
| 31 | 
    private static final int NUM_MOVES = 23;  | 
|
| 32 | 
     | 
|
| 33 | 
    private int mDist;  | 
|
| 34 | 
    private boolean mFresh;  | 
|
| 35 | 
    private long mID;  | 
|
| 36 | 
    private final long[] mMoves;  | 
|
| 37 | 
     | 
|
| 38 | 
    private final int[][] mPermittedAngles;  | 
|
| 39 | 
    private final int[] mCornerQuat, mTmp;  | 
|
| 40 | 
     | 
|
| 41 | 
    // QUATS[i]*QUATS[j] = QUATS[QUAT_MULT[i][j]]  | 
|
| 42 | 
    static final int[][] QUAT_MULT = new int[][]  | 
|
| 43 | 
        {
   | 
|
| 44 | 
          {  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,},
   | 
|
| 45 | 
          {  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11,  0, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 12,},
   | 
|
| 46 | 
          {  2,  3,  4,  5,  6,  7,  8,  9, 10, 11,  0,  1, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 12, 13,},
   | 
|
| 47 | 
          {  3,  4,  5,  6,  7,  8,  9, 10, 11,  0,  1,  2, 15, 16, 17, 18, 19, 20, 21, 22, 23, 12, 13, 14,},
   | 
|
| 48 | 
          {  4,  5,  6,  7,  8,  9, 10, 11,  0,  1,  2,  3, 16, 17, 18, 19, 20, 21, 22, 23, 12, 13, 14, 15,},
   | 
|
| 49 | 
          {  5,  6,  7,  8,  9, 10, 11,  0,  1,  2,  3,  4, 17, 18, 19, 20, 21, 22, 23, 12, 13, 14, 15, 16,},
   | 
|
| 50 | 
          {  6,  7,  8,  9, 10, 11,  0,  1,  2,  3,  4,  5, 18, 19, 20, 21, 22, 23, 12, 13, 14, 15, 16, 17,},
   | 
|
| 51 | 
          {  7,  8,  9, 10, 11,  0,  1,  2,  3,  4,  5,  6, 19, 20, 21, 22, 23, 12, 13, 14, 15, 16, 17, 18,},
   | 
|
| 52 | 
          {  8,  9, 10, 11,  0,  1,  2,  3,  4,  5,  6,  7, 20, 21, 22, 23, 12, 13, 14, 15, 16, 17, 18, 19,},
   | 
|
| 53 | 
          {  9, 10, 11,  0,  1,  2,  3,  4,  5,  6,  7,  8, 21, 22, 23, 12, 13, 14, 15, 16, 17, 18, 19, 20,},
   | 
|
| 54 | 
          { 10, 11,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 22, 23, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,},
   | 
|
| 55 | 
          { 11,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 23, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22,},
   | 
|
| 56 | 
          { 12, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13,  0, 11, 10,  9,  8,  7,  6,  5,  4,  3,  2,  1,},
   | 
|
| 57 | 
          { 13, 12, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14,  1,  0, 11, 10,  9,  8,  7,  6,  5,  4,  3,  2,},
   | 
|
| 58 | 
          { 14, 13, 12, 23, 22, 21, 20, 19, 18, 17, 16, 15,  2,  1,  0, 11, 10,  9,  8,  7,  6,  5,  4,  3,},
   | 
|
| 59 | 
          { 15, 14, 13, 12, 23, 22, 21, 20, 19, 18, 17, 16,  3,  2,  1,  0, 11, 10,  9,  8,  7,  6,  5,  4,},
   | 
|
| 60 | 
          { 16, 15, 14, 13, 12, 23, 22, 21, 20, 19, 18, 17,  4,  3,  2,  1,  0, 11, 10,  9,  8,  7,  6,  5,},
   | 
|
| 61 | 
          { 17, 16, 15, 14, 13, 12, 23, 22, 21, 20, 19, 18,  5,  4,  3,  2,  1,  0, 11, 10,  9,  8,  7,  6,},
   | 
|
| 62 | 
          { 18, 17, 16, 15, 14, 13, 12, 23, 22, 21, 20, 19,  6,  5,  4,  3,  2,  1,  0, 11, 10,  9,  8,  7,},
   | 
|
| 63 | 
          { 19, 18, 17, 16, 15, 14, 13, 12, 23, 22, 21, 20,  7,  6,  5,  4,  3,  2,  1,  0, 11, 10,  9,  8,},
   | 
|
| 64 | 
          { 20, 19, 18, 17, 16, 15, 14, 13, 12, 23, 22, 21,  8,  7,  6,  5,  4,  3,  2,  1,  0, 11, 10,  9,},
   | 
|
| 65 | 
          { 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 23, 22,  9,  8,  7,  6,  5,  4,  3,  2,  1,  0, 11, 10,},
   | 
|
| 66 | 
          { 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 23, 10,  9,  8,  7,  6,  5,  4,  3,  2,  1,  0, 11,},
   | 
|
| 67 | 
          { 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10,  9,  8,  7,  6,  5,  4,  3,  2,  1,  0,}
   | 
|
| 68 | 
    };  | 
|
| 69 | 
     | 
|
| 70 | 
    // quat indices that make corner cubits bandage the puzzle.  | 
|
| 71 | 
    private static final int[][] BAD_CORNER_QUATS = new int[][]  | 
|
| 72 | 
        {
   | 
|
| 73 | 
          { 2, 8,17,23},
   | 
|
| 74 | 
          { 5,11,14,20},
   | 
|
| 75 | 
    };  | 
|
| 76 | 
     | 
|
| 77 | 
    ///////////////////////////////////////////////////////////////////////////////////////////////////  | 
|
| 78 | 
     | 
|
| 79 | 
    public ScrambleStateSquare1(long id, int dist)  | 
|
| 80 | 
        {
   | 
|
| 81 | 
    mCornerQuat = new int[8];  | 
|
| 82 | 
    mTmp = new int[8];  | 
|
| 83 | 
    mPermittedAngles = new int[2][12];  | 
|
| 84 | 
     | 
|
| 85 | 
    mDist = dist;  | 
|
| 86 | 
    mFresh = true;  | 
|
| 87 | 
    mID = id;  | 
|
| 88 | 
    mMoves = createMoves(mID);  | 
|
| 89 | 
    }  | 
|
| 90 | 
     | 
|
| 91 | 
    ///////////////////////////////////////////////////////////////////////////////////////////////////  | 
|
| 92 | 
     | 
|
| 93 | 
    private void setNotFresh()  | 
|
| 94 | 
        {
   | 
|
| 95 | 
    mFresh = false;  | 
|
| 96 | 
    }  | 
|
| 97 | 
     | 
|
| 98 | 
    ///////////////////////////////////////////////////////////////////////////////////////////////////  | 
|
| 99 | 
     | 
|
| 100 | 
    private boolean isFresh()  | 
|
| 101 | 
        {
   | 
|
| 102 | 
    return mFresh;  | 
|
| 103 | 
    }  | 
|
| 104 | 
     | 
|
| 105 | 
    ///////////////////////////////////////////////////////////////////////////////////////////////////  | 
|
| 106 | 
     | 
|
| 107 | 
    public static void computeGraph()  | 
|
| 108 | 
        {
   | 
|
| 109 | 
    ArrayList<ScrambleStateSquare1> graph;  | 
|
| 110 | 
     | 
|
| 111 | 
    ScrambleStateSquare1 bsg = new ScrambleStateSquare1(0,0);  | 
|
| 112 | 
    graph = new ArrayList<>();  | 
|
| 113 | 
    graph.add(bsg);  | 
|
| 114 | 
     | 
|
| 115 | 
    android.util.Log.e("D", "INSERTING");
   | 
|
| 116 | 
     | 
|
| 117 | 
    insertChildren(graph,0);  | 
|
| 118 | 
     | 
|
| 119 | 
    //android.util.Log.e("D", "PRUNING "+graph.size());
   | 
|
| 120 | 
     | 
|
| 121 | 
    // pruneGraph(graph);  | 
|
| 122 | 
     | 
|
| 123 | 
    android.util.Log.e("D", "REMAPPING "+graph.size());
   | 
|
| 124 | 
     | 
|
| 125 | 
    remapGraph(graph);  | 
|
| 126 | 
     | 
|
| 127 | 
    int num = graph.size();  | 
|
| 128 | 
        android.util.Log.e("D", "\n"+num+" states\n");
   | 
|
| 129 | 
     | 
|
| 130 | 
    for(int i=0; i<num; i++)  | 
|
| 131 | 
          {
   | 
|
| 132 | 
    bsg = graph.get(i);  | 
|
| 133 | 
          android.util.Log.e("D", formatMoves(bsg));
   | 
|
| 134 | 
    }  | 
|
| 135 | 
    }  | 
|
| 136 | 
     | 
|
| 137 | 
    ///////////////////////////////////////////////////////////////////////////////////////////////////  | 
|
| 138 | 
     | 
|
| 139 | 
    private static void insertChildren(ArrayList<ScrambleStateSquare1> list, long id)  | 
|
| 140 | 
        {
   | 
|
| 141 | 
    ScrambleStateSquare1 bsg = findState(list,id);  | 
|
| 142 | 
     | 
|
| 143 | 
    if( bsg==null )  | 
|
| 144 | 
          {
   | 
|
| 145 | 
          android.util.Log.e("D", "error: "+id+" doesn't exist");
   | 
|
| 146 | 
    return;  | 
|
| 147 | 
    }  | 
|
| 148 | 
     | 
|
| 149 | 
    int dist = bsg.mDist;  | 
|
| 150 | 
    if( dist>6 ) return;  | 
|
| 151 | 
     | 
|
| 152 | 
    for(int i=0; i<NUM_MOVES; i++)  | 
|
| 153 | 
          {
   | 
|
| 154 | 
    long moveID = bsg.getMoveID(i);  | 
|
| 155 | 
     | 
|
| 156 | 
    if( moveID!=INVALID_MOVE )  | 
|
| 157 | 
            {
   | 
|
| 158 | 
    ScrambleStateSquare1 tmp = findState(list,moveID);  | 
|
| 159 | 
     | 
|
| 160 | 
    if( tmp==null )  | 
|
| 161 | 
              {
   | 
|
| 162 | 
    tmp = new ScrambleStateSquare1(moveID,dist+1);  | 
|
| 163 | 
    list.add(tmp);  | 
|
| 164 | 
    }  | 
|
| 165 | 
    }  | 
|
| 166 | 
    }  | 
|
| 167 | 
     | 
|
| 168 | 
    for(int i=0; i<NUM_MOVES; i++)  | 
|
| 169 | 
          {
   | 
|
| 170 | 
    long moveID = bsg.getMoveID(i);  | 
|
| 171 | 
     | 
|
| 172 | 
    if( moveID!=INVALID_MOVE )  | 
|
| 173 | 
            {
   | 
|
| 174 | 
    ScrambleStateSquare1 tmp = findState(list,moveID);  | 
|
| 175 | 
     | 
|
| 176 | 
    if( tmp.isFresh() )  | 
|
| 177 | 
              {
   | 
|
| 178 | 
    tmp.setNotFresh();  | 
|
| 179 | 
    insertChildren(list,moveID);  | 
|
| 180 | 
    }  | 
|
| 181 | 
    }  | 
|
| 182 | 
    }  | 
|
| 183 | 
    }  | 
|
| 184 | 
     | 
|
| 185 | 
    ///////////////////////////////////////////////////////////////////////////////////////////////////  | 
|
| 186 | 
     | 
|
| 187 | 
    private static void pruneGraph(ArrayList<ScrambleStateSquare1> list)  | 
|
| 188 | 
        {
   | 
|
| 189 | 
    int num = list.size(), numAxis;  | 
|
| 190 | 
    boolean pruned = false;  | 
|
| 191 | 
    ScrambleStateSquare1 bsg;  | 
|
| 192 | 
     | 
|
| 193 | 
    for(int i=0; i<num; i++)  | 
|
| 194 | 
          {
   | 
|
| 195 | 
    bsg = list.get(i);  | 
|
| 196 | 
    numAxis = bsg.numAxis();  | 
|
| 197 | 
     | 
|
| 198 | 
    if( numAxis<2 )  | 
|
| 199 | 
            {
   | 
|
| 200 | 
    list.remove(i);  | 
|
| 201 | 
    long id = bsg.getID();  | 
|
| 202 | 
    pruned = true;  | 
|
| 203 | 
    remapID(list,id,INVALID_MOVE);  | 
|
| 204 | 
    break;  | 
|
| 205 | 
    }  | 
|
| 206 | 
    }  | 
|
| 207 | 
     | 
|
| 208 | 
    if( pruned ) pruneGraph(list);  | 
|
| 209 | 
    }  | 
|
| 210 | 
     | 
|
| 211 | 
    ///////////////////////////////////////////////////////////////////////////////////////////////////  | 
|
| 212 | 
     | 
|
| 213 | 
    private static void remapGraph(ArrayList<ScrambleStateSquare1> list)  | 
|
| 214 | 
        {
   | 
|
| 215 | 
    long id;  | 
|
| 216 | 
    int num = list.size();  | 
|
| 217 | 
    ScrambleStateSquare1 bsg;  | 
|
| 218 | 
     | 
|
| 219 | 
    for(int i=0; i<num; i++ )  | 
|
| 220 | 
          {
   | 
|
| 221 | 
    bsg = list.get(i);  | 
|
| 222 | 
    id = bsg.getID();  | 
|
| 223 | 
    bsg.setID(i);  | 
|
| 224 | 
    remapID(list,id,i);  | 
|
| 225 | 
    }  | 
|
| 226 | 
    }  | 
|
| 227 | 
     | 
|
| 228 | 
    ///////////////////////////////////////////////////////////////////////////////////////////////////  | 
|
| 229 | 
     | 
|
| 230 | 
    private static void remapID(ArrayList<ScrambleStateSquare1> list, long id, long newId)  | 
|
| 231 | 
        {
   | 
|
| 232 | 
    ScrambleStateSquare1 bsg;  | 
|
| 233 | 
    int size = list.size();  | 
|
| 234 | 
     | 
|
| 235 | 
    for(int i=0; i<size; i++)  | 
|
| 236 | 
          {
   | 
|
| 237 | 
    bsg = list.get(i);  | 
|
| 238 | 
     | 
|
| 239 | 
    for(int j=0; j<NUM_MOVES; j++)  | 
|
| 240 | 
            {
   | 
|
| 241 | 
    if( bsg.getMoveID(j)==id ) bsg.setMoveID(j,newId);  | 
|
| 242 | 
    }  | 
|
| 243 | 
    }  | 
|
| 244 | 
    }  | 
|
| 245 | 
     | 
|
| 246 | 
    ///////////////////////////////////////////////////////////////////////////////////////////////////  | 
|
| 247 | 
     | 
|
| 248 | 
    private static ScrambleStateSquare1 findState(ArrayList<ScrambleStateSquare1> list, long id)  | 
|
| 249 | 
        {
   | 
|
| 250 | 
    ScrambleStateSquare1 bsg;  | 
|
| 251 | 
    int num = list.size();  | 
|
| 252 | 
     | 
|
| 253 | 
    for(int i=0; i<num; i++)  | 
|
| 254 | 
          {
   | 
|
| 255 | 
    bsg= list.get(i);  | 
|
| 256 | 
    if( bsg.getID() == id ) return bsg;  | 
|
| 257 | 
    }  | 
|
| 258 | 
     | 
|
| 259 | 
    return null;  | 
|
| 260 | 
    }  | 
|
| 261 | 
     | 
|
| 262 | 
    ///////////////////////////////////////////////////////////////////////////////////////////////////  | 
|
| 263 | 
     | 
|
| 264 | 
    private static String formatMoves(ScrambleStateSquare1 bsg)  | 
|
| 265 | 
        {
   | 
|
| 266 | 
    String x = getTable(bsg,0);  | 
|
| 267 | 
    String y = getTable(bsg,11);  | 
|
| 268 | 
    String z = getTable(bsg,12);  | 
|
| 269 | 
     | 
|
| 270 | 
        //return "    new ScrambleStateGraph( new int[][] { "+x+", "+y+", "+z+" } ),";
   | 
|
| 271 | 
     | 
|
| 272 | 
    long id = bsg.getID();  | 
|
| 273 | 
     | 
|
| 274 | 
    return id+" "+x+" , "+y+" , "+z;  | 
|
| 275 | 
    }  | 
|
| 276 | 
     | 
|
| 277 | 
    ///////////////////////////////////////////////////////////////////////////////////////////////////  | 
|
| 278 | 
     | 
|
| 279 | 
    private static String getTable(ScrambleStateSquare1 sc, int index)  | 
|
| 280 | 
        {
   | 
|
| 281 | 
    String ret = "";  | 
|
| 282 | 
    long m;  | 
|
| 283 | 
    int half = (NUM_MOVES)/2;  | 
|
| 284 | 
     | 
|
| 285 | 
    if( index==11 )  | 
|
| 286 | 
          {
   | 
|
| 287 | 
    m = sc.getMoveID(index);  | 
|
| 288 | 
          if( m==INVALID_MOVE ) return formatL("{}");
   | 
|
| 289 | 
    ret += formatRet(ret,0,1,m);  | 
|
| 290 | 
    }  | 
|
| 291 | 
    else  | 
|
| 292 | 
          {
   | 
|
| 293 | 
    for(int i=0; i<half; i++)  | 
|
| 294 | 
            {
   | 
|
| 295 | 
    m = sc.getMoveID(index+i);  | 
|
| 296 | 
    int row = index==0 ? 0:2;  | 
|
| 297 | 
    int angle = i+1;  | 
|
| 298 | 
    if( m!=INVALID_MOVE ) ret += formatRet(ret,row,angle,m);  | 
|
| 299 | 
    }  | 
|
| 300 | 
    }  | 
|
| 301 | 
     | 
|
| 302 | 
        return formatL("{" + ret + "}");
   | 
|
| 303 | 
    }  | 
|
| 304 | 
     | 
|
| 305 | 
    ///////////////////////////////////////////////////////////////////////////////////////////////////  | 
|
| 306 | 
     | 
|
| 307 | 
    private static String formatRet(String str, int row, int angle, long id)  | 
|
| 308 | 
        {
   | 
|
| 309 | 
    String ret = str.length()!=0 ? " ,":" ";  | 
|
| 310 | 
     | 
|
| 311 | 
    ret += row;  | 
|
| 312 | 
    ret += angle<0 ? "," : ",";  | 
|
| 313 | 
    ret += angle;  | 
|
| 314 | 
     | 
|
| 315 | 
             if( id< 10 ) ret += (",  "+id);
   | 
|
| 316 | 
        else if( id<100 ) ret += (", " +id);
   | 
|
| 317 | 
        else              ret += (","  +id);
   | 
|
| 318 | 
     | 
|
| 319 | 
    return ret;  | 
|
| 320 | 
    }  | 
|
| 321 | 
     | 
|
| 322 | 
    ///////////////////////////////////////////////////////////////////////////////////////////////////  | 
|
| 323 | 
     | 
|
| 324 | 
    private static final int LENGTH = 28;  | 
|
| 325 | 
     | 
|
| 326 | 
    private static String formatL(String input)  | 
|
| 327 | 
        {
   | 
|
| 328 | 
    int len = input.length();  | 
|
| 329 | 
    String ret = input;  | 
|
| 330 | 
    for(int i=0 ;i<LENGTH-len; i++) ret += " ";  | 
|
| 331 | 
    return ret;  | 
|
| 332 | 
    }  | 
|
| 333 | 
     | 
|
| 334 | 
    ///////////////////////////////////////////////////////////////////////////////////////////////////  | 
|
| 335 | 
     | 
|
| 336 | 
    private long getID()  | 
|
| 337 | 
        {
   | 
|
| 338 | 
    return mID;  | 
|
| 339 | 
    }  | 
|
| 340 | 
     | 
|
| 341 | 
    ///////////////////////////////////////////////////////////////////////////////////////////////////  | 
|
| 342 | 
     | 
|
| 343 | 
    private void setID(long id)  | 
|
| 344 | 
        {
   | 
|
| 345 | 
    mID = id;  | 
|
| 346 | 
    }  | 
|
| 347 | 
     | 
|
| 348 | 
    ///////////////////////////////////////////////////////////////////////////////////////////////////  | 
|
| 349 | 
     | 
|
| 350 | 
    private long getMoveID(int index)  | 
|
| 351 | 
        {
   | 
|
| 352 | 
    return (index>=0 && index<NUM_MOVES) ? mMoves[index] : -1;  | 
|
| 353 | 
    }  | 
|
| 354 | 
     | 
|
| 355 | 
    ///////////////////////////////////////////////////////////////////////////////////////////////////  | 
|
| 356 | 
     | 
|
| 357 | 
    private void setMoveID(int index, long newID)  | 
|
| 358 | 
        {
   | 
|
| 359 | 
    if( index>=0 && index<NUM_MOVES ) mMoves[index] = newID;  | 
|
| 360 | 
    }  | 
|
| 361 | 
     | 
|
| 362 | 
    ///////////////////////////////////////////////////////////////////////////////////////////////////  | 
|
| 363 | 
     | 
|
| 364 | 
    private int numAxis()  | 
|
| 365 | 
        {
   | 
|
| 366 | 
    int num = 0;  | 
|
| 367 | 
    int half = (NUM_MOVES)/2;  | 
|
| 368 | 
     | 
|
| 369 | 
    for(int i=0; i<half; i++)  | 
|
| 370 | 
          {
   | 
|
| 371 | 
    if( mMoves[i]!=INVALID_MOVE )  | 
|
| 372 | 
            {
   | 
|
| 373 | 
    num++;  | 
|
| 374 | 
    break;  | 
|
| 375 | 
    }  | 
|
| 376 | 
    }  | 
|
| 377 | 
     | 
|
| 378 | 
    for(int i=half; i<NUM_MOVES-1; i++)  | 
|
| 379 | 
          {
   | 
|
| 380 | 
    if( mMoves[i]!=INVALID_MOVE )  | 
|
| 381 | 
            {
   | 
|
| 382 | 
    num++;  | 
|
| 383 | 
    break;  | 
|
| 384 | 
    }  | 
|
| 385 | 
    }  | 
|
| 386 | 
     | 
|
| 387 | 
    if( mMoves[NUM_MOVES-1]!=INVALID_MOVE ) num++;  | 
|
| 388 | 
     | 
|
| 389 | 
    return num;  | 
|
| 390 | 
    }  | 
|
| 391 | 
     | 
|
| 392 | 
    ///////////////////////////////////////////////////////////////////////////////////////////////////  | 
|
| 393 | 
     | 
|
| 394 | 
    private long[] createMoves(long id)  | 
|
| 395 | 
        {
   | 
|
| 396 | 
    long[] ret = new long[NUM_MOVES];  | 
|
| 397 | 
    fillCornerQuat(id);  | 
|
| 398 | 
    computePermittedAngles();  | 
|
| 399 | 
     | 
|
| 400 | 
    generateUMoves(ret, 0);  | 
|
| 401 | 
    generateSMoves(ret,11);  | 
|
| 402 | 
    generateLMoves(ret,12);  | 
|
| 403 | 
     | 
|
| 404 | 
    return ret;  | 
|
| 405 | 
    }  | 
|
| 406 | 
     | 
|
| 407 | 
    ///////////////////////////////////////////////////////////////////////////////////////////////////  | 
|
| 408 | 
     | 
|
| 409 | 
    private void generateUMoves(long[] table, int index)  | 
|
| 410 | 
        {
   | 
|
| 411 | 
    for(int angle=1; angle<12; angle++)  | 
|
| 412 | 
          {
   | 
|
| 413 | 
    table[index+angle-1] = mPermittedAngles[1][angle]==1 ? updateCornerQuats(0,2,angle) : INVALID_MOVE;  | 
|
| 414 | 
    }  | 
|
| 415 | 
    }  | 
|
| 416 | 
     | 
|
| 417 | 
    ///////////////////////////////////////////////////////////////////////////////////////////////////  | 
|
| 418 | 
     | 
|
| 419 | 
    private void generateLMoves(long[] table, int index)  | 
|
| 420 | 
        {
   | 
|
| 421 | 
    for(int angle=1; angle<12; angle++)  | 
|
| 422 | 
          {
   | 
|
| 423 | 
    table[index+angle-1] = mPermittedAngles[0][angle]==1 ? updateCornerQuats(0,0,angle) : INVALID_MOVE;  | 
|
| 424 | 
    }  | 
|
| 425 | 
    }  | 
|
| 426 | 
     | 
|
| 427 | 
    ///////////////////////////////////////////////////////////////////////////////////////////////////  | 
|
| 428 | 
     | 
|
| 429 | 
    private void generateSMoves(long[] table, int index)  | 
|
| 430 | 
        {
   | 
|
| 431 | 
    table[index] = updateCornerQuats(1,1,1);  | 
|
| 432 | 
    }  | 
|
| 433 | 
     | 
|
| 434 | 
    ///////////////////////////////////////////////////////////////////////////////////////////////////  | 
|
| 435 | 
     | 
|
| 436 | 
    private void fillCornerQuat(long id)  | 
|
| 437 | 
        {
   | 
|
| 438 | 
    int NUM_QUATS = 24;  | 
|
| 439 | 
     | 
|
| 440 | 
    for(int i=0; i<8; i++)  | 
|
| 441 | 
          {
   | 
|
| 442 | 
    mCornerQuat[i] = (int)(id%NUM_QUATS);  | 
|
| 443 | 
    id/=NUM_QUATS;  | 
|
| 444 | 
    }  | 
|
| 445 | 
    }  | 
|
| 446 | 
     | 
|
| 447 | 
    ///////////////////////////////////////////////////////////////////////////////////////////////////  | 
|
| 448 | 
     | 
|
| 449 | 
    private static long returnID(int[] cornerQuat)  | 
|
| 450 | 
        {
   | 
|
| 451 | 
    int NUM_QUATS = 24;  | 
|
| 452 | 
    long mult=1,ret=0;  | 
|
| 453 | 
     | 
|
| 454 | 
    for(int i=0; i<8; i++)  | 
|
| 455 | 
          {
   | 
|
| 456 | 
    ret += mult*cornerQuat[i];  | 
|
| 457 | 
    mult*=NUM_QUATS;  | 
|
| 458 | 
    }  | 
|
| 459 | 
     | 
|
| 460 | 
    return ret;  | 
|
| 461 | 
    }  | 
|
| 462 | 
     | 
|
| 463 | 
    ///////////////////////////////////////////////////////////////////////////////////////////////////  | 
|
| 464 | 
     | 
|
| 465 | 
    private boolean cornerIsUp(int index)  | 
|
| 466 | 
        {
   | 
|
| 467 | 
    return ((index<4) ^ (mCornerQuat[index]>=12));  | 
|
| 468 | 
    }  | 
|
| 469 | 
     | 
|
| 470 | 
    ///////////////////////////////////////////////////////////////////////////////////////////////////  | 
|
| 471 | 
     | 
|
| 472 | 
    private boolean cornerIsLeft(int index)  | 
|
| 473 | 
        {
   | 
|
| 474 | 
    int q = mCornerQuat[index];  | 
|
| 475 | 
     | 
|
| 476 | 
    switch(index)  | 
|
| 477 | 
          {
   | 
|
| 478 | 
    case 0:  | 
|
| 479 | 
    case 4: return ((q>=3 && q<= 7) || (q>=18 && q<=22));  | 
|
| 480 | 
    case 1:  | 
|
| 481 | 
    case 5: return ((q>=6 && q<=10) || (q>=15 && q<=19));  | 
|
| 482 | 
    case 2:  | 
|
| 483 | 
    case 6: return ((q==0 || q==1 || (q>=9 && q<=11)) || (q>=12 && q<=16));  | 
|
| 484 | 
    case 3:  | 
|
| 485 | 
    case 7: return ((q>=0 && q<=4) || (q==12 || q==13 || (q>=21 && q<=23)));  | 
|
| 486 | 
    }  | 
|
| 487 | 
     | 
|
| 488 | 
    return false;  | 
|
| 489 | 
    }  | 
|
| 490 | 
     | 
|
| 491 | 
    ///////////////////////////////////////////////////////////////////////////////////////////////////  | 
|
| 492 | 
     | 
|
| 493 | 
    private int makeQuat(int axis,int index)  | 
|
| 494 | 
        {
   | 
|
| 495 | 
    if( axis==1 ) return 13;  | 
|
| 496 | 
    if( index<0 ) index+=12;  | 
|
| 497 | 
    return index;  | 
|
| 498 | 
    }  | 
|
| 499 | 
     | 
|
| 500 | 
    ///////////////////////////////////////////////////////////////////////////////////////////////////  | 
|
| 501 | 
     | 
|
| 502 | 
    private boolean cornerBelongs(int index, int axis, int layer)  | 
|
| 503 | 
        {
   | 
|
| 504 | 
    if( axis==0 )  | 
|
| 505 | 
          {
   | 
|
| 506 | 
    boolean up = cornerIsUp(index);  | 
|
| 507 | 
    return ((up && layer==2) || (!up && layer==0));  | 
|
| 508 | 
    }  | 
|
| 509 | 
    else  | 
|
| 510 | 
          {
   | 
|
| 511 | 
    boolean le = cornerIsLeft(index);  | 
|
| 512 | 
    return ((le && layer==0) || (!le && layer==1));  | 
|
| 513 | 
    }  | 
|
| 514 | 
    }  | 
|
| 515 | 
     | 
|
| 516 | 
    ///////////////////////////////////////////////////////////////////////////////////////////////////  | 
|
| 517 | 
     | 
|
| 518 | 
    private long updateCornerQuats(int axis, int layer, int index)  | 
|
| 519 | 
        {
   | 
|
| 520 | 
    int quat = makeQuat(axis,index);  | 
|
| 521 | 
     | 
|
| 522 | 
    for(int corner=0; corner<8; corner++)  | 
|
| 523 | 
          {
   | 
|
| 524 | 
    if( cornerBelongs(corner,axis,layer) )  | 
|
| 525 | 
            {
   | 
|
| 526 | 
    int curr = mCornerQuat[corner];  | 
|
| 527 | 
    mTmp[corner] = QUAT_MULT[quat][curr];  | 
|
| 528 | 
    }  | 
|
| 529 | 
    else  | 
|
| 530 | 
            {
   | 
|
| 531 | 
    mTmp[corner] = mCornerQuat[corner];  | 
|
| 532 | 
    }  | 
|
| 533 | 
    }  | 
|
| 534 | 
     | 
|
| 535 | 
    return returnID(mTmp);  | 
|
| 536 | 
    }  | 
|
| 537 | 
     | 
|
| 538 | 
    ///////////////////////////////////////////////////////////////////////////////////////////////////  | 
|
| 539 | 
     | 
|
| 540 | 
    private boolean quatIsBad(int quatIndex, int corner)  | 
|
| 541 | 
        {
   | 
|
| 542 | 
    int index = (corner%2);  | 
|
| 543 | 
     | 
|
| 544 | 
    return ( quatIndex==BAD_CORNER_QUATS[index][0] ||  | 
|
| 545 | 
    quatIndex==BAD_CORNER_QUATS[index][1] ||  | 
|
| 546 | 
    quatIndex==BAD_CORNER_QUATS[index][2] ||  | 
|
| 547 | 
    quatIndex==BAD_CORNER_QUATS[index][3] );  | 
|
| 548 | 
    }  | 
|
| 549 | 
     | 
|
| 550 | 
    ///////////////////////////////////////////////////////////////////////////////////////////////////  | 
|
| 551 | 
     | 
|
| 552 | 
    private int isPermittedDo(int angle)  | 
|
| 553 | 
        {
   | 
|
| 554 | 
    for(int corner=0; corner<8; corner++)  | 
|
| 555 | 
          {
   | 
|
| 556 | 
    if( !cornerIsUp(corner) )  | 
|
| 557 | 
            {
   | 
|
| 558 | 
    int currQuat = mCornerQuat[corner];  | 
|
| 559 | 
    int finalQuat= QUAT_MULT[angle][currQuat];  | 
|
| 560 | 
    if( quatIsBad(finalQuat,corner) ) return 0;  | 
|
| 561 | 
    }  | 
|
| 562 | 
    }  | 
|
| 563 | 
     | 
|
| 564 | 
    return 1;  | 
|
| 565 | 
    }  | 
|
| 566 | 
     | 
|
| 567 | 
    ///////////////////////////////////////////////////////////////////////////////////////////////////  | 
|
| 568 | 
     | 
|
| 569 | 
    private int isPermittedUp(int angle)  | 
|
| 570 | 
        {
   | 
|
| 571 | 
    for(int corner=0; corner<8; corner++)  | 
|
| 572 | 
          {
   | 
|
| 573 | 
    if( cornerIsUp(corner) )  | 
|
| 574 | 
            {
   | 
|
| 575 | 
    int currQuat = mCornerQuat[corner];  | 
|
| 576 | 
    int finalQuat= QUAT_MULT[angle][currQuat];  | 
|
| 577 | 
    if( quatIsBad(finalQuat,corner) ) return 0;  | 
|
| 578 | 
    }  | 
|
| 579 | 
    }  | 
|
| 580 | 
     | 
|
| 581 | 
    return 1;  | 
|
| 582 | 
    }  | 
|
| 583 | 
     | 
|
| 584 | 
    ///////////////////////////////////////////////////////////////////////////////////////////////////  | 
|
| 585 | 
     | 
|
| 586 | 
    private void computePermittedAngles()  | 
|
| 587 | 
        {
   | 
|
| 588 | 
    for(int angle=0; angle<12; angle++)  | 
|
| 589 | 
          {
   | 
|
| 590 | 
    mPermittedAngles[0][angle] = isPermittedDo(angle);  | 
|
| 591 | 
    mPermittedAngles[1][angle] = isPermittedUp(angle);  | 
|
| 592 | 
    }  | 
|
| 593 | 
    }  | 
|
| 594 | 
    }  | 
|
| src/main/java/org/distorted/objects/Cubit.java | ||
|---|---|---|
| 76 | 76 | 
    float xd,yd,zd,wd;  | 
| 77 | 77 | 
    float diff, mindiff = Float.MAX_VALUE;  | 
| 78 | 78 | 
    int ret=0;  | 
| 79 | 
    int num_quats = mParent.QUATS.length;  | 
|
| 79 | 
        int num_quats = mParent.OBJECT_QUATS.length;
   | 
|
| 80 | 80 | 
    Static4D qt;  | 
| 81 | 81 | 
     | 
| 82 | 82 | 
    for(int q=0; q<num_quats; q++)  | 
| 83 | 83 | 
          {
   | 
| 84 | 
    qt = mParent.QUATS[q];  | 
|
| 84 | 
          qt = mParent.OBJECT_QUATS[q];
   | 
|
| 85 | 85 | 
     | 
| 86 | 86 | 
    xd = x - qt.get0();  | 
| 87 | 87 | 
    yd = y - qt.get1();  | 
| ... | ... | |
| 189 | 189 | 
     | 
| 190 | 190 | 
    int removeRotationNow(Static4D quat)  | 
| 191 | 191 | 
        {
   | 
| 192 | 
    Static4D q = QuatHelper.quatMultiply(quat,mParent.QUATS[mQuatIndex]);  | 
|
| 192 | 
        Static4D q = QuatHelper.quatMultiply(quat,mParent.OBJECT_QUATS[mQuatIndex]);
   | 
|
| 193 | 193 | 
    mQuatIndex = normalizeScrambleQuat(q);  | 
| 194 | 194 | 
     | 
| 195 | 195 | 
    modifyCurrentPosition(quat);  | 
| src/main/java/org/distorted/objects/TwistyCube.java | ||
|---|---|---|
| 37 | 37 | 
     | 
| 38 | 38 | 
    class TwistyCube extends TwistyObject  | 
| 39 | 39 | 
    {
   | 
| 40 | 
    // the three rotation axis of a RubikCube. Must be normalized.  | 
|
| 41 | 40 | 
    static final Static3D[] ROT_AXIS = new Static3D[]  | 
| 42 | 41 | 
             {
   | 
| 43 | 42 | 
    new Static3D(1,0,0),  | 
| ... | ... | |
| 45 | 44 | 
    new Static3D(0,0,1)  | 
| 46 | 45 | 
    };  | 
| 47 | 46 | 
     | 
| 48 | 
      private static final int[] BASIC_ANGLE = new int[] { 4,4,4 };
   | 
|
| 49 | 
     | 
|
| 50 | 47 | 
    private static final int[] FACE_COLORS = new int[]  | 
| 51 | 48 | 
             {
   | 
| 52 | 49 | 
    COLOR_YELLOW, COLOR_WHITE,  | 
| ... | ... | |
| 54 | 51 | 
    COLOR_RED , COLOR_ORANGE  | 
| 55 | 52 | 
    };  | 
| 56 | 53 | 
     | 
| 57 | 
    // All legal rotation quats of a RubikCube of any size.  | 
|
| 58 | 
    // Here's how to compute this:  | 
|
| 59 | 
    // 1) compute how many rotations there are (RubikCube of any size = 24)  | 
|
| 60 | 
    // 2) take the AXIS, angles of rotation (90 in RubikCube's case) compute the basic quaternions  | 
|
| 61 | 
    // (i.e. rotations of 1 basic angle along each of the axis) and from there start semi-randomly  | 
|
| 62 | 
    // multiplying them and eventually you'll find all (24) legal rotations.  | 
|
| 63 | 
    // Example program in C, res/raw/compute_quats.c , is included.  | 
|
| 64 | 
    private static final Static4D[] QUATS = new Static4D[]  | 
|
| 65 | 
             {
   | 
|
| 66 | 
    new Static4D( 0.0f, 0.0f, 0.0f, 1.0f),  | 
|
| 67 | 
    new Static4D( 1.0f, 0.0f, 0.0f, 0.0f),  | 
|
| 68 | 
    new Static4D( 0.0f, 1.0f, 0.0f, 0.0f),  | 
|
| 69 | 
    new Static4D( 0.0f, 0.0f, 1.0f, 0.0f),  | 
|
| 70 | 
     | 
|
| 71 | 
    new Static4D( SQ2/2, SQ2/2, 0.0f , 0.0f),  | 
|
| 72 | 
    new Static4D( SQ2/2, -SQ2/2, 0.0f , 0.0f),  | 
|
| 73 | 
    new Static4D( SQ2/2, 0.0f, SQ2/2, 0.0f),  | 
|
| 74 | 
    new Static4D(-SQ2/2, 0.0f, SQ2/2, 0.0f),  | 
|
| 75 | 
    new Static4D( SQ2/2, 0.0f, 0.0f, SQ2/2),  | 
|
| 76 | 
    new Static4D( SQ2/2, 0.0f, 0.0f, -SQ2/2),  | 
|
| 77 | 
    new Static4D( 0.0f, SQ2/2, SQ2/2, 0.0f),  | 
|
| 78 | 
    new Static4D( 0.0f, SQ2/2, -SQ2/2, 0.0f),  | 
|
| 79 | 
    new Static4D( 0.0f, SQ2/2, 0.0f, SQ2/2),  | 
|
| 80 | 
    new Static4D( 0.0f, SQ2/2, 0.0f, -SQ2/2),  | 
|
| 81 | 
    new Static4D( 0.0f, 0.0f, SQ2/2, SQ2/2),  | 
|
| 82 | 
    new Static4D( 0.0f, 0.0f, SQ2/2, -SQ2/2),  | 
|
| 83 | 
     | 
|
| 84 | 
    new Static4D( 0.5f, 0.5f, 0.5f, 0.5f),  | 
|
| 85 | 
    new Static4D( 0.5f, 0.5f, -0.5f, 0.5f),  | 
|
| 86 | 
    new Static4D( 0.5f, 0.5f, -0.5f, -0.5f),  | 
|
| 87 | 
    new Static4D( 0.5f, -0.5f, 0.5f, -0.5f),  | 
|
| 88 | 
    new Static4D( -0.5f, -0.5f, -0.5f, 0.5f),  | 
|
| 89 | 
    new Static4D( -0.5f, 0.5f, -0.5f, -0.5f),  | 
|
| 90 | 
    new Static4D( -0.5f, 0.5f, 0.5f, -0.5f),  | 
|
| 91 | 
    new Static4D( -0.5f, 0.5f, 0.5f, 0.5f)  | 
|
| 92 | 
    };  | 
|
| 93 | 
     | 
|
| 94 | 
    private static final double[][] VERTICES = new double[][]  | 
|
| 95 | 
              {
   | 
|
| 96 | 
                  { 0.5, 0.5, 0.5 },
   | 
|
| 97 | 
                  { 0.5, 0.5,-0.5 },
   | 
|
| 98 | 
                  { 0.5,-0.5, 0.5 },
   | 
|
| 99 | 
                  { 0.5,-0.5,-0.5 },
   | 
|
| 100 | 
                  {-0.5, 0.5, 0.5 },
   | 
|
| 101 | 
                  {-0.5, 0.5,-0.5 },
   | 
|
| 102 | 
                  {-0.5,-0.5, 0.5 },
   | 
|
| 103 | 
                  {-0.5,-0.5,-0.5 },
   | 
|
| 104 | 
    };  | 
|
| 105 | 
     | 
|
| 106 | 
    private static final int[][] VERT_INDEXES = new int[][]  | 
|
| 107 | 
              {
   | 
|
| 108 | 
                  {2,3,1,0},   // counterclockwise!
   | 
|
| 109 | 
                  {7,6,4,5},
   | 
|
| 110 | 
                  {4,0,1,5},
   | 
|
| 111 | 
                  {7,3,2,6},
   | 
|
| 112 | 
                  {6,2,0,4},
   | 
|
| 113 | 
                  {3,7,5,1}
   | 
|
| 114 | 
    };  | 
|
| 115 | 
     | 
|
| 116 | 
    private static final float[][] STICKERS = new float[][]  | 
|
| 117 | 
              {
   | 
|
| 118 | 
                  { -0.5f, -0.5f, 0.5f, -0.5f, 0.5f, 0.5f, -0.5f, 0.5f }
   | 
|
| 119 | 
    };  | 
|
| 120 | 
     | 
|
| 121 | 
    private static final ObjectSticker[] mStickers;  | 
|
| 122 | 
     | 
|
| 123 | 
    static  | 
|
| 124 | 
        {
   | 
|
| 125 | 
    final float radius = 0.10f;  | 
|
| 126 | 
    final float stroke = 0.08f;  | 
|
| 127 | 
        final float[] radii = {radius,radius,radius,radius};
   | 
|
| 128 | 
    mStickers = new ObjectSticker[STICKERS.length];  | 
|
| 129 | 
    mStickers[0] = new ObjectSticker(STICKERS[0],null,radii,stroke );  | 
|
| 130 | 
    }  | 
|
| 131 | 
     | 
|
| 132 | 54 | 
    private int mCurrState;  | 
| 133 | 55 | 
    private int mIndexExcluded;  | 
| 134 | 56 | 
    private final ScrambleState[] mStates;  | 
| 135 | 57 | 
    private int[][] mScrambleTable;  | 
| 136 | 58 | 
    private int[] mNumOccurences;  | 
| 59 | 
    private Static4D[] mQuats;  | 
|
| 60 | 
    private int[] mBasicAngle;  | 
|
| 61 | 
    private ObjectSticker[] mStickers;  | 
|
| 137 | 62 | 
     | 
| 138 | 63 | 
    ///////////////////////////////////////////////////////////////////////////////////////////////////  | 
| 139 | 64 | 
     | 
| ... | ... | |
| 188 | 113 | 
    return ret;  | 
| 189 | 114 | 
    }  | 
| 190 | 115 | 
     | 
| 116 | 
    ///////////////////////////////////////////////////////////////////////////////////////////////////  | 
|
| 117 | 
     | 
|
| 118 | 
    private void initializeQuats()  | 
|
| 119 | 
        {
   | 
|
| 120 | 
    mQuats = new Static4D[]  | 
|
| 121 | 
             {
   | 
|
| 122 | 
    new Static4D( 0.0f, 0.0f, 0.0f, 1.0f),  | 
|
| 123 | 
    new Static4D( 1.0f, 0.0f, 0.0f, 0.0f),  | 
|
| 124 | 
    new Static4D( 0.0f, 1.0f, 0.0f, 0.0f),  | 
|
| 125 | 
    new Static4D( 0.0f, 0.0f, 1.0f, 0.0f),  | 
|
| 126 | 
     | 
|
| 127 | 
    new Static4D( SQ2/2, SQ2/2, 0.0f , 0.0f),  | 
|
| 128 | 
    new Static4D( SQ2/2, -SQ2/2, 0.0f , 0.0f),  | 
|
| 129 | 
    new Static4D( SQ2/2, 0.0f, SQ2/2, 0.0f),  | 
|
| 130 | 
    new Static4D(-SQ2/2, 0.0f, SQ2/2, 0.0f),  | 
|
| 131 | 
    new Static4D( SQ2/2, 0.0f, 0.0f, SQ2/2),  | 
|
| 132 | 
    new Static4D( SQ2/2, 0.0f, 0.0f, -SQ2/2),  | 
|
| 133 | 
    new Static4D( 0.0f, SQ2/2, SQ2/2, 0.0f),  | 
|
| 134 | 
    new Static4D( 0.0f, SQ2/2, -SQ2/2, 0.0f),  | 
|
| 135 | 
    new Static4D( 0.0f, SQ2/2, 0.0f, SQ2/2),  | 
|
| 136 | 
    new Static4D( 0.0f, SQ2/2, 0.0f, -SQ2/2),  | 
|
| 137 | 
    new Static4D( 0.0f, 0.0f, SQ2/2, SQ2/2),  | 
|
| 138 | 
    new Static4D( 0.0f, 0.0f, SQ2/2, -SQ2/2),  | 
|
| 139 | 
     | 
|
| 140 | 
    new Static4D( 0.5f, 0.5f, 0.5f, 0.5f),  | 
|
| 141 | 
    new Static4D( 0.5f, 0.5f, -0.5f, 0.5f),  | 
|
| 142 | 
    new Static4D( 0.5f, 0.5f, -0.5f, -0.5f),  | 
|
| 143 | 
    new Static4D( 0.5f, -0.5f, 0.5f, -0.5f),  | 
|
| 144 | 
    new Static4D( -0.5f, -0.5f, -0.5f, 0.5f),  | 
|
| 145 | 
    new Static4D( -0.5f, 0.5f, -0.5f, -0.5f),  | 
|
| 146 | 
    new Static4D( -0.5f, 0.5f, 0.5f, -0.5f),  | 
|
| 147 | 
    new Static4D( -0.5f, 0.5f, 0.5f, 0.5f)  | 
|
| 148 | 
    };  | 
|
| 149 | 
    }  | 
|
| 150 | 
     | 
|
| 191 | 151 | 
    ///////////////////////////////////////////////////////////////////////////////////////////////////  | 
| 192 | 152 | 
     | 
| 193 | 153 | 
    int[] getSolvedQuats(int cubit, int numLayers)  | 
| 194 | 154 | 
        {
   | 
| 155 | 
    if( mQuats ==null ) initializeQuats();  | 
|
| 195 | 156 | 
    int status = retCubitSolvedStatus(cubit,numLayers);  | 
| 196 | 
        return status<0 ? null : buildSolvedQuats(MovementCube.FACE_AXIS[status],QUATS);
   | 
|
| 157 | 
        return status<0 ? null : buildSolvedQuats(MovementCube.FACE_AXIS[status], mQuats);
   | 
|
| 197 | 158 | 
    }  | 
| 198 | 159 | 
     | 
| 199 | 160 | 
    ///////////////////////////////////////////////////////////////////////////////////////////////////  | 
| ... | ... | |
| 211 | 172 | 
    default: num = 5; extraI = 0; extraV = 0; height = 0.045f; break;  | 
| 212 | 173 | 
    }  | 
| 213 | 174 | 
     | 
| 175 | 
    double[][] vertices = new double[][]  | 
|
| 176 | 
              {
   | 
|
| 177 | 
                  { 0.5, 0.5, 0.5 },
   | 
|
| 178 | 
                  { 0.5, 0.5,-0.5 },
   | 
|
| 179 | 
                  { 0.5,-0.5, 0.5 },
   | 
|
| 180 | 
                  { 0.5,-0.5,-0.5 },
   | 
|
| 181 | 
                  {-0.5, 0.5, 0.5 },
   | 
|
| 182 | 
                  {-0.5, 0.5,-0.5 },
   | 
|
| 183 | 
                  {-0.5,-0.5, 0.5 },
   | 
|
| 184 | 
                  {-0.5,-0.5,-0.5 },
   | 
|
| 185 | 
    };  | 
|
| 186 | 
     | 
|
| 187 | 
    int[][] vert_indices = new int[][]  | 
|
| 188 | 
              {
   | 
|
| 189 | 
                  {2,3,1,0},   // counterclockwise!
   | 
|
| 190 | 
                  {7,6,4,5},
   | 
|
| 191 | 
                  {4,0,1,5},
   | 
|
| 192 | 
                  {7,3,2,6},
   | 
|
| 193 | 
                  {6,2,0,4},
   | 
|
| 194 | 
                  {3,7,5,1}
   | 
|
| 195 | 
    };  | 
|
| 196 | 
     | 
|
| 214 | 197 | 
        float[][] bands     = new float[][] { {height,35,0.5f,0.7f,num,extraI,extraV} };
   | 
| 215 | 198 | 
        int[] bandIndices   = new int[] { 0,0,0,0,0,0};
   | 
| 216 | 199 | 
        float[][] corners   = new float[][] { {0.036f,0.12f} };
   | 
| ... | ... | |
| 218 | 201 | 
        float[][] centers   = new float[][] { {0.0f, 0.0f, 0.0f} };
   | 
| 219 | 202 | 
        int[] centerIndices = new int[] { 0,0,0,0,0,0,0,0 };
   | 
| 220 | 203 | 
     | 
| 221 | 
        return new ObjectShape(VERTICES,VERT_INDEXES,bands,bandIndices,corners,cornerIndices,centers,centerIndices,getNumCubitFaces(), null);
   | 
|
| 204 | 
        return new ObjectShape(vertices,vert_indices,bands,bandIndices,corners,cornerIndices,centers,centerIndices,getNumCubitFaces(), null);
   | 
|
| 222 | 205 | 
    }  | 
| 223 | 206 | 
     | 
| 224 | 207 | 
    ///////////////////////////////////////////////////////////////////////////////////////////////////  | 
| 225 | 208 | 
     | 
| 226 | 209 | 
    Static4D getQuat(int cubit, int numLayers)  | 
| 227 | 210 | 
        {
   | 
| 228 | 
    return QUATS[0];  | 
|
| 211 | 
    if( mQuats ==null ) initializeQuats();  | 
|
| 212 | 
    return mQuats[0];  | 
|
| 229 | 213 | 
    }  | 
| 230 | 214 | 
     | 
| 231 | 215 | 
    ///////////////////////////////////////////////////////////////////////////////////////////////////  | 
| ... | ... | |
| 253 | 237 | 
     | 
| 254 | 238 | 
    ObjectSticker retSticker(int face)  | 
| 255 | 239 | 
        {
   | 
| 240 | 
    if( mStickers==null )  | 
|
| 241 | 
          {
   | 
|
| 242 | 
          final float[][] STICKERS = new float[][]  { { -0.5f, -0.5f, 0.5f, -0.5f, 0.5f, 0.5f, -0.5f, 0.5f } };
   | 
|
| 243 | 
    final float radius = 0.10f;  | 
|
| 244 | 
    final float stroke = 0.08f;  | 
|
| 245 | 
          final float[] radii = {radius,radius,radius,radius};
   | 
|
| 246 | 
    mStickers = new ObjectSticker[STICKERS.length];  | 
|
| 247 | 
    mStickers[0] = new ObjectSticker(STICKERS[0],null,radii,stroke );  | 
|
| 248 | 
    }  | 
|
| 249 | 
     | 
|
| 256 | 250 | 
    return mStickers[face/NUM_FACES];  | 
| 257 | 251 | 
    }  | 
| 258 | 252 | 
     | 
| ... | ... | |
| 281 | 275 | 
     | 
| 282 | 276 | 
    Static4D[] getQuats()  | 
| 283 | 277 | 
        {
   | 
| 284 | 
    return QUATS;  | 
|
| 278 | 
    if( mQuats ==null ) initializeQuats();  | 
|
| 279 | 
    return mQuats;  | 
|
| 285 | 280 | 
    }  | 
| 286 | 281 | 
     | 
| 287 | 282 | 
    ///////////////////////////////////////////////////////////////////////////////////////////////////  | 
| ... | ... | |
| 326 | 321 | 
     | 
| 327 | 322 | 
    int getNumStickerTypes(int numLayers)  | 
| 328 | 323 | 
        {
   | 
| 329 | 
        return STICKERS.length;
   | 
|
| 324 | 
        return 1;
   | 
|
| 330 | 325 | 
    }  | 
| 331 | 326 | 
     | 
| 332 | 327 | 
    ///////////////////////////////////////////////////////////////////////////////////////////////////  | 
| ... | ... | |
| 369 | 364 | 
     | 
| 370 | 365 | 
    public int[] getBasicAngle()  | 
| 371 | 366 | 
        {
   | 
| 372 | 
    return BASIC_ANGLE;  | 
|
| 367 | 
        if( mBasicAngle ==null ) mBasicAngle = new int[] { 4,4,4 };
   | 
|
| 368 | 
    return mBasicAngle;  | 
|
| 373 | 369 | 
    }  | 
| 374 | 370 | 
     | 
| 375 | 371 | 
    ///////////////////////////////////////////////////////////////////////////////////////////////////  | 
| src/main/java/org/distorted/objects/TwistyObject.java | ||
|---|---|---|
| 88 | 88 | 
    private static final int POST_ROTATION_MILLISEC = 500;  | 
| 89 | 89 | 
     | 
| 90 | 90 | 
    MeshBase[] mMeshes;  | 
| 91 | 
    final Static4D[] QUATS;  | 
|
| 91 | 
      final Static4D[] OBJECT_QUATS;
   | 
|
| 92 | 92 | 
    final Cubit[] CUBITS;  | 
| 93 | 93 | 
    final int NUM_FACES;  | 
| 94 | 94 | 
    final int NUM_TEXTURES;  | 
| 95 | 95 | 
    final int NUM_CUBITS;  | 
| 96 | 96 | 
    final int NUM_AXIS;  | 
| 97 | 
    final int NUM_QUATS;  | 
|
| 97 | 98 | 
     | 
| 98 | 99 | 
    private final int mNumCubitFaces;  | 
| 99 | 100 | 
    private final Static3D[] mAxis;  | 
| ... | ... | |
| 158 | 159 | 
    if( mCuts==null ) for(int i=0; i<mAxis.length; i++) mNumCuts[i] = 0;  | 
| 159 | 160 | 
    else for(int i=0; i<mAxis.length; i++) mNumCuts[i] = mCuts[i].length;  | 
| 160 | 161 | 
     | 
| 161 | 
    QUATS = getQuats();  | 
|
| 162 | 
        OBJECT_QUATS = getQuats();
   | 
|
| 162 | 163 | 
    NUM_CUBITS = mOrigPos.length;  | 
| 163 | 164 | 
    NUM_FACES = getNumFaces();  | 
| 164 | 165 | 
    NUM_TEXTURES = getNumStickerTypes(mNumLayers)*NUM_FACES;  | 
| 165 | 166 | 
    NUM_AXIS = mAxis.length;  | 
| 167 | 
    NUM_QUATS = OBJECT_QUATS.length;  | 
|
| 166 | 168 | 
     | 
| 167 | 169 | 
    boolean bandaged=false;  | 
| 168 | 170 | 
     | 
| ... | ... | |
| 213 | 215 | 
    mTexture = new DistortedTexture();  | 
| 214 | 216 | 
    mEffects = new DistortedEffects();  | 
| 215 | 217 | 
     | 
| 216 | 
    int num_quats = QUATS.length;  | 
|
| 217 | 
    for(int q=0; q<num_quats; q++)  | 
|
| 218 | 
    for(int q=0; q<NUM_QUATS; q++)  | 
|
| 218 | 219 | 
          {
   | 
| 219 | 
    VertexEffectQuaternion vq = new VertexEffectQuaternion(QUATS[q],CENTER);  | 
|
| 220 | 
          VertexEffectQuaternion vq = new VertexEffectQuaternion(OBJECT_QUATS[q],CENTER);
   | 
|
| 220 | 221 | 
    vq.setMeshAssociation(0,q);  | 
| 221 | 222 | 
    mEffects.apply(vq);  | 
| 222 | 223 | 
    }  | 
| ... | ... | |
| 343 | 344 | 
     | 
| 344 | 345 | 
    private void createDataStructuresForSolved(int numLayers)  | 
| 345 | 346 | 
        {
   | 
| 346 | 
        mTmpQuats = new int[QUATS.length];
   | 
|
| 347 | 
        mTmpQuats = new int[NUM_QUATS];
   | 
|
| 347 | 348 | 
    mSolvedQuats = new int[NUM_CUBITS][];  | 
| 348 | 349 | 
     | 
| 349 | 350 | 
    for(int c=0; c<NUM_CUBITS; c++)  | 
| ... | ... | |
| 432 | 433 | 
        {
   | 
| 433 | 434 | 
    if( mQuatMult==null )  | 
| 434 | 435 | 
          {
   | 
| 435 | 
    int len = QUATS.length;  | 
|
| 436 | 
    mQuatMult = new int[len][len];  | 
|
| 436 | 
    mQuatMult = new int[NUM_QUATS][NUM_QUATS];  | 
|
| 437 | 437 | 
     | 
| 438 | 
          for(int i=0; i<len; i++)
   | 
|
| 439 | 
            for(int j=0; j<len; j++) mQuatMult[i][j] = -1;
   | 
|
| 438 | 
          for(int i=0; i<NUM_QUATS; i++)
   | 
|
| 439 | 
            for(int j=0; j<NUM_QUATS; j++) mQuatMult[i][j] = -1;
   | 
|
| 440 | 440 | 
    }  | 
| 441 | 441 | 
     | 
| 442 | 442 | 
    if( mQuatMult[index1][index2]==-1 )  | 
| ... | ... | |
| 499 | 499 | 
    float MAXDIFF = 0.01f;  | 
| 500 | 500 | 
    float[] center= mOrigPos[centerNum];  | 
| 501 | 501 | 
    Static4D sc = new Static4D(center[0], center[1], center[2], 1.0f);  | 
| 502 | 
    Static4D result = QuatHelper.rotateVectorByQuat(sc,QUATS[quatNum]);  | 
|
| 502 | 
        Static4D result = QuatHelper.rotateVectorByQuat(sc,OBJECT_QUATS[quatNum]);
   | 
|
| 503 | 503 | 
     | 
| 504 | 504 | 
    float x = result.get0();  | 
| 505 | 505 | 
    float y = result.get1();  | 
| ... | ... | |
| 532 | 532 | 
        {
   | 
| 533 | 533 | 
    if( mScramble==null )  | 
| 534 | 534 | 
          {
   | 
| 535 | 
    int numQuats = QUATS.length;  | 
|
| 536 | 
    mScramble = new int[numQuats][NUM_CUBITS];  | 
|
| 535 | 
    mScramble = new int[NUM_QUATS][NUM_CUBITS];  | 
|
| 537 | 536 | 
    mColors = new int[NUM_CUBITS];  | 
| 538 | 537 | 
     | 
| 539 | 
          for(int q=0; q<numQuats; q++)
   | 
|
| 538 | 
          for(int q=0; q<NUM_QUATS; q++)
   | 
|
| 540 | 539 | 
    for(int c=0; c<NUM_CUBITS; c++) mScramble[q][c] = computeScramble(q,c);  | 
| 541 | 540 | 
    }  | 
| 542 | 541 | 
     | 
| ... | ... | |
| 815 | 814 | 
     | 
| 816 | 815 | 
    int mulQuat(int q1, int q2)  | 
| 817 | 816 | 
        {
   | 
| 818 | 
        Static4D result = QuatHelper.quatMultiply(QUATS[q1],QUATS[q2]);
   | 
|
| 817 | 
        Static4D result = QuatHelper.quatMultiply(OBJECT_QUATS[q1],OBJECT_QUATS[q2]);
   | 
|
| 819 | 818 | 
     | 
| 820 | 819 | 
    float rX = result.get0();  | 
| 821 | 820 | 
    float rY = result.get1();  | 
| ... | ... | |
| 825 | 824 | 
    final float MAX_ERROR = 0.1f;  | 
| 826 | 825 | 
    float dX,dY,dZ,dW;  | 
| 827 | 826 | 
     | 
| 828 | 
        for(int i=0; i<QUATS.length; i++)
   | 
|
| 827 | 
        for(int i=0; i<NUM_QUATS; i++)
   | 
|
| 829 | 828 | 
          {
   | 
| 830 | 
    dX = QUATS[i].get0() - rX;  | 
|
| 831 | 
    dY = QUATS[i].get1() - rY;  | 
|
| 832 | 
    dZ = QUATS[i].get2() - rZ;  | 
|
| 833 | 
    dW = QUATS[i].get3() - rW;  | 
|
| 829 | 
          dX = OBJECT_QUATS[i].get0() - rX;
   | 
|
| 830 | 
          dY = OBJECT_QUATS[i].get1() - rY;
   | 
|
| 831 | 
          dZ = OBJECT_QUATS[i].get2() - rZ;
   | 
|
| 832 | 
          dW = OBJECT_QUATS[i].get3() - rW;
   | 
|
| 834 | 833 | 
     | 
| 835 | 834 | 
    if( dX<MAX_ERROR && dX>-MAX_ERROR &&  | 
| 836 | 835 | 
    dY<MAX_ERROR && dY>-MAX_ERROR &&  | 
| 837 | 836 | 
    dZ<MAX_ERROR && dZ>-MAX_ERROR &&  | 
| 838 | 837 | 
    dW<MAX_ERROR && dW>-MAX_ERROR ) return i;  | 
| 839 | 838 | 
     | 
| 840 | 
    dX = QUATS[i].get0() + rX;  | 
|
| 841 | 
    dY = QUATS[i].get1() + rY;  | 
|
| 842 | 
    dZ = QUATS[i].get2() + rZ;  | 
|
| 843 | 
    dW = QUATS[i].get3() + rW;  | 
|
| 839 | 
          dX = OBJECT_QUATS[i].get0() + rX;
   | 
|
| 840 | 
          dY = OBJECT_QUATS[i].get1() + rY;
   | 
|
| 841 | 
          dZ = OBJECT_QUATS[i].get2() + rZ;
   | 
|
| 842 | 
          dW = OBJECT_QUATS[i].get3() + rW;
   | 
|
| 844 | 843 | 
     | 
| 845 | 844 | 
    if( dX<MAX_ERROR && dX>-MAX_ERROR &&  | 
| 846 | 845 | 
    dY<MAX_ERROR && dY>-MAX_ERROR &&  | 
| ... | ... | |
| 946 | 945 | 
          {
   | 
| 947 | 946 | 
    mQuatDebug[i] = CUBITS[i].restorePreferences(preferences);  | 
| 948 | 947 | 
     | 
| 949 | 
          if( mQuatDebug[i]>=0 && mQuatDebug[i]<QUATS.length)
   | 
|
| 948 | 
          if( mQuatDebug[i]>=0 && mQuatDebug[i]<NUM_QUATS)
   | 
|
| 950 | 949 | 
            {
   | 
| 951 | 
    CUBITS[i].modifyCurrentPosition(QUATS[mQuatDebug[i]]);  | 
|
| 950 | 
            CUBITS[i].modifyCurrentPosition(OBJECT_QUATS[mQuatDebug[i]]);
   | 
|
| 952 | 951 | 
    mMesh.setEffectAssociation(i, CUBITS[i].computeAssociation(),mQuatDebug[i]);  | 
| 953 | 952 | 
    }  | 
| 954 | 953 | 
    else  | 
Also available in: Unified diff
Remove statics from the Cube classes.