Revision ad38d800
Added by Leszek Koltunski about 5 years ago
| src/main/java/org/distorted/main/RubikSurfaceView.java | ||
|---|---|---|
| 34 | 34 | 
    import org.distorted.library.type.Static3D;  | 
| 35 | 35 | 
    import org.distorted.library.type.Static4D;  | 
| 36 | 36 | 
    import org.distorted.objects.RubikObject;  | 
| 37 | 
    import org.distorted.objects.RubikObjectMovement;
   | 
|
| 37 | 
    import org.distorted.objects.RubikMovementObject;
   | 
|
| 38 | 38 | 
    import org.distorted.solvers.SolverMain;  | 
| 39 | 39 | 
    import org.distorted.states.RubikState;  | 
| 40 | 40 | 
    import org.distorted.states.RubikStatePlay;  | 
| ... | ... | |
| 71 | 71 | 
     | 
| 72 | 72 | 
    private RubikRenderer mRenderer;  | 
| 73 | 73 | 
    private RubikPreRender mPreRender;  | 
| 74 | 
        private RubikObjectMovement mMovement;
   | 
|
| 74 | 
        private RubikMovementObject mMovement;
   | 
|
| 75 | 75 | 
    private boolean mDragging, mBeginningRotation, mContinuingRotation;  | 
| 76 | 76 | 
    private int mScreenWidth, mScreenHeight, mScreenMin;  | 
| 77 | 77 | 
     | 
| ... | ... | |
| 140 | 140 | 
     | 
| 141 | 141 | 
    ///////////////////////////////////////////////////////////////////////////////////////////////////  | 
| 142 | 142 | 
     | 
| 143 | 
        void setMovement(RubikObjectMovement movement)
   | 
|
| 143 | 
        void setMovement(RubikMovementObject movement)
   | 
|
| 144 | 144 | 
          {
   | 
| 145 | 145 | 
    mMovement = movement;  | 
| 146 | 146 | 
    }  | 
| src/main/java/org/distorted/objects/RubikCube.java | ||
|---|---|---|
| 43 | 43 | 
    static final float SQ2 = (float)Math.sqrt(2);  | 
| 44 | 44 | 
     | 
| 45 | 45 | 
    // the three rotation axis of a RubikCube. Must be normalized.  | 
| 46 | 
    static final Static3D[] AXIS = new Static3D[]  | 
|
| 46 | 
      static final Static3D[] ROT_AXIS = new Static3D[]
   | 
|
| 47 | 47 | 
             {
   | 
| 48 | 48 | 
    new Static3D(1,0,0),  | 
| 49 | 49 | 
    new Static3D(0,1,0),  | 
| 50 | 50 | 
    new Static3D(0,0,1)  | 
| 51 | 51 | 
    };  | 
| 52 | 52 | 
     | 
| 53 | 
    // the six axis that determine the faces  | 
|
| 54 | 
    static final Static3D[] FACE_AXIS = new Static3D[]  | 
|
| 55 | 
             {
   | 
|
| 56 | 
    new Static3D(1,0,0), new Static3D(-1,0,0),  | 
|
| 57 | 
    new Static3D(0,1,0), new Static3D(0,-1,0),  | 
|
| 58 | 
    new Static3D(0,0,1), new Static3D(0,0,-1)  | 
|
| 59 | 
    };  | 
|
| 60 | 
     | 
|
| 53 | 61 | 
    private static final int[] FACE_COLORS = new int[]  | 
| 54 | 62 | 
             {
   | 
| 55 | 
               0xffffff00, 0xffffffff,   // AXIS[0]right (right-YELLOW) AXIS[0]left (left  -WHITE)
   | 
|
| 56 | 
               0xff0000ff, 0xff00ff00,   // AXIS[1]right (top  -BLUE  ) AXIS[1]left (bottom-GREEN)
   | 
|
| 57 | 
               0xffff0000, 0xffb5651d    // AXIS[2]right (front-RED   ) AXIS[2]left (back  -BROWN)
   | 
|
| 63 | 
               0xffffff00, 0xffffffff,   // FACE_AXIS[0] (right-YELLOW) FACE_AXIS[1] (left  -WHITE)
   | 
|
| 64 | 
               0xff0000ff, 0xff00ff00,   // FACE_AXIS[2] (top  -BLUE  ) FACE_AXIS[3] (bottom-GREEN)
   | 
|
| 65 | 
               0xffff0000, 0xffb5651d    // FACE_AXIS[4] (front-RED   ) FACE_AXIS[5] (back  -BROWN)
   | 
|
| 58 | 66 | 
    };  | 
| 59 | 67 | 
     | 
| 60 | 68 | 
    // All legal rotation quats of a RubikCube of any size.  | 
| ... | ... | |
| 304 | 312 | 
     | 
| 305 | 313 | 
    public Static3D[] getRotationAxis()  | 
| 306 | 314 | 
        {
   | 
| 307 | 
    return AXIS;  | 
|
| 315 | 
        return ROT_AXIS;
   | 
|
| 308 | 316 | 
    }  | 
| 309 | 317 | 
     | 
| 310 | 318 | 
    ///////////////////////////////////////////////////////////////////////////////////////////////////  | 
| src/main/java/org/distorted/objects/RubikCubeMovement.java | ||
|---|---|---|
| 1 | 
    ///////////////////////////////////////////////////////////////////////////////////////////////////  | 
|
| 2 | 
    // Copyright 2020 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.objects;  | 
|
| 21 | 
     | 
|
| 22 | 
    ///////////////////////////////////////////////////////////////////////////////////////////////////  | 
|
| 23 | 
     | 
|
| 24 | 
    class RubikCubeMovement extends RubikObjectMovement  | 
|
| 25 | 
    {
   | 
|
| 26 | 
    RubikCubeMovement()  | 
|
| 27 | 
        {
   | 
|
| 28 | 
    super(RubikCube.AXIS, 2, 0.5f, 0.5f);  | 
|
| 29 | 
    }  | 
|
| 30 | 
     | 
|
| 31 | 
    ///////////////////////////////////////////////////////////////////////////////////////////////////  | 
|
| 32 | 
     | 
|
| 33 | 
    boolean isInsideFace(float[] p)  | 
|
| 34 | 
        {
   | 
|
| 35 | 
    return ( p[0]<=0.5f && p[0]>=-0.5f && p[1]<=0.5f && p[1]>=-0.5f );  | 
|
| 36 | 
    }  | 
|
| 37 | 
    }  | 
|
| src/main/java/org/distorted/objects/RubikDino.java | ||
|---|---|---|
| 51 | 51 | 
    private static final float ANGLE_FACES = (float)((180/Math.PI)*(2*Math.asin(SQ3/3))); // angle between two faces of a tetrahedron  | 
| 52 | 52 | 
     | 
| 53 | 53 | 
    // the four rotation axis of a RubikDino. Must be normalized.  | 
| 54 | 
    static final Static3D[] AXIS = new Static3D[]  | 
|
| 54 | 
      static final Static3D[] ROT_AXIS = new Static3D[]
   | 
|
| 55 | 55 | 
             {
   | 
| 56 | 56 | 
    new Static3D(+SQ3/3,+SQ3/3,+SQ3/3),  | 
| 57 | 57 | 
    new Static3D(+SQ3/3,+SQ3/3,-SQ3/3),  | 
| ... | ... | |
| 59 | 59 | 
    new Static3D(+SQ3/3,-SQ3/3,-SQ3/3)  | 
| 60 | 60 | 
    };  | 
| 61 | 61 | 
     | 
| 62 | 
    // the six axis that determine the faces  | 
|
| 63 | 
    static final Static3D[] FACE_AXIS = new Static3D[]  | 
|
| 64 | 
             {
   | 
|
| 65 | 
    new Static3D(1,0,0), new Static3D(-1,0,0),  | 
|
| 66 | 
    new Static3D(0,1,0), new Static3D(0,-1,0),  | 
|
| 67 | 
    new Static3D(0,0,1), new Static3D(0,0,-1)  | 
|
| 68 | 
    };  | 
|
| 69 | 
     | 
|
| 62 | 70 | 
    private static final int[] FACE_COLORS = new int[]  | 
| 63 | 71 | 
             {
   | 
| 64 | 
               0xffffff00, 0xffffffff,   // (right-YELLOW) (left  -WHITE)
   | 
|
| 65 | 
               0xff0000ff, 0xff00ff00,   // (top  -BLUE  ) (bottom-GREEN)
   | 
|
| 66 | 
               0xffff0000, 0xffb5651d    // (front-RED   ) (back  -BROWN)
   | 
|
| 72 | 
               0xffffff00, 0xffffffff,   // FACE_AXIS[0] (right-YELLOW) FACE_AXIS[1] (left  -WHITE)
   | 
|
| 73 | 
               0xff0000ff, 0xff00ff00,   // FACE_AXIS[2] (top  -BLUE  ) FACE_AXIS[3] (bottom-GREEN)
   | 
|
| 74 | 
               0xffff0000, 0xffb5651d    // FACE_AXIS[4] (front-RED   ) FACE_AXIS[5] (back  -BROWN)
   | 
|
| 67 | 75 | 
    };  | 
| 68 | 76 | 
     | 
| 69 | 77 | 
    // All legal rotation quats of a RubikDino  | 
| ... | ... | |
| 328 | 336 | 
     | 
| 329 | 337 | 
    public Static3D[] getRotationAxis()  | 
| 330 | 338 | 
        {
   | 
| 331 | 
    return AXIS;  | 
|
| 339 | 
        return ROT_AXIS;
   | 
|
| 332 | 340 | 
    }  | 
| 333 | 341 | 
     | 
| 334 | 342 | 
    ///////////////////////////////////////////////////////////////////////////////////////////////////  | 
| src/main/java/org/distorted/objects/RubikDinoMovement.java | ||
|---|---|---|
| 1 | 
    ///////////////////////////////////////////////////////////////////////////////////////////////////  | 
|
| 2 | 
    // Copyright 2020 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.objects;  | 
|
| 21 | 
     | 
|
| 22 | 
    ///////////////////////////////////////////////////////////////////////////////////////////////////  | 
|
| 23 | 
     | 
|
| 24 | 
    class RubikDinoMovement extends RubikObjectMovement  | 
|
| 25 | 
    {
   | 
|
| 26 | 
    RubikDinoMovement()  | 
|
| 27 | 
        {
   | 
|
| 28 | 
    super(RubikDino.AXIS, 1.5f, 0.5f, 0.5f);  | 
|
| 29 | 
    }  | 
|
| 30 | 
     | 
|
| 31 | 
    ///////////////////////////////////////////////////////////////////////////////////////////////////  | 
|
| 32 | 
     | 
|
| 33 | 
    boolean isInsideFace(float[] p)  | 
|
| 34 | 
        {
   | 
|
| 35 | 
    return false;//( p[0]<=0.5f && p[0]>=-0.5f && p[1]<=0.5f && p[1]>=-0.5f );  | 
|
| 36 | 
    }  | 
|
| 37 | 
    }  | 
|
| src/main/java/org/distorted/objects/RubikMovementCube.java | ||
|---|---|---|
| 1 | 
    ///////////////////////////////////////////////////////////////////////////////////////////////////  | 
|
| 2 | 
    // Copyright 2020 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.objects;  | 
|
| 21 | 
     | 
|
| 22 | 
    ///////////////////////////////////////////////////////////////////////////////////////////////////  | 
|
| 23 | 
     | 
|
| 24 | 
    class RubikMovementCube extends RubikMovementObject  | 
|
| 25 | 
    {
   | 
|
| 26 | 
    RubikMovementCube()  | 
|
| 27 | 
        {
   | 
|
| 28 | 
    super(RubikCube.ROT_AXIS, RubikCube.FACE_AXIS, 0.5f, 0.5f);  | 
|
| 29 | 
    }  | 
|
| 30 | 
     | 
|
| 31 | 
    ///////////////////////////////////////////////////////////////////////////////////////////////////  | 
|
| 32 | 
     | 
|
| 33 | 
    boolean isInsideFace(float[] p)  | 
|
| 34 | 
        {
   | 
|
| 35 | 
    return ( p[0]<=0.5f && p[0]>=-0.5f && p[1]<=0.5f && p[1]>=-0.5f );  | 
|
| 36 | 
    }  | 
|
| 37 | 
    }  | 
|
| src/main/java/org/distorted/objects/RubikMovementDino.java | ||
|---|---|---|
| 1 | 
    ///////////////////////////////////////////////////////////////////////////////////////////////////  | 
|
| 2 | 
    // Copyright 2020 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.objects;  | 
|
| 21 | 
     | 
|
| 22 | 
    ///////////////////////////////////////////////////////////////////////////////////////////////////  | 
|
| 23 | 
     | 
|
| 24 | 
    class RubikMovementDino extends RubikMovementObject  | 
|
| 25 | 
    {
   | 
|
| 26 | 
    RubikMovementDino()  | 
|
| 27 | 
        {
   | 
|
| 28 | 
    super(RubikDino.ROT_AXIS, RubikDino.FACE_AXIS, 0.5f, 0.5f);  | 
|
| 29 | 
    }  | 
|
| 30 | 
     | 
|
| 31 | 
    ///////////////////////////////////////////////////////////////////////////////////////////////////  | 
|
| 32 | 
     | 
|
| 33 | 
    boolean isInsideFace(float[] p)  | 
|
| 34 | 
        {
   | 
|
| 35 | 
    return ( p[0]<=0.5f && p[0]>=-0.5f && p[1]<=0.5f && p[1]>=-0.5f );  | 
|
| 36 | 
    }  | 
|
| 37 | 
    }  | 
|
| src/main/java/org/distorted/objects/RubikMovementObject.java | ||
|---|---|---|
| 1 | 
    ///////////////////////////////////////////////////////////////////////////////////////////////////  | 
|
| 2 | 
    // Copyright 2020 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.objects;  | 
|
| 21 | 
     | 
|
| 22 | 
    import org.distorted.library.type.Static2D;  | 
|
| 23 | 
    import org.distorted.library.type.Static3D;  | 
|
| 24 | 
    import org.distorted.library.type.Static4D;  | 
|
| 25 | 
     | 
|
| 26 | 
    ///////////////////////////////////////////////////////////////////////////////////////////////////  | 
|
| 27 | 
     | 
|
| 28 | 
    public abstract class RubikMovementObject  | 
|
| 29 | 
      {
   | 
|
| 30 | 
    private int mLastTouchedAxis;  | 
|
| 31 | 
    private float[] mPoint, mCamera, mTouch;  | 
|
| 32 | 
    private float[] mPoint2D, mMove2D;  | 
|
| 33 | 
    private float[][][] mCastAxis;  | 
|
| 34 | 
    private int mLastTouchedLR;  | 
|
| 35 | 
    private int mNumRotAxis, mNumFaceAxis, mNumFacesPerAxis;  | 
|
| 36 | 
    private float mDistanceCenterFace3D, mDistanceCenterFace2D;  | 
|
| 37 | 
    private Static3D[] mRotAxis, mFaceAxis;  | 
|
| 38 | 
     | 
|
| 39 | 
    ///////////////////////////////////////////////////////////////////////////////////////////////////  | 
|
| 40 | 
     | 
|
| 41 | 
    abstract boolean isInsideFace(float[] point);  | 
|
| 42 | 
     | 
|
| 43 | 
    ///////////////////////////////////////////////////////////////////////////////////////////////////  | 
|
| 44 | 
     | 
|
| 45 | 
    RubikMovementObject(Static3D[] rotAxis, Static3D[] faceAxis, float distance3D, float distance2D)  | 
|
| 46 | 
        {
   | 
|
| 47 | 
    mPoint = new float[3];  | 
|
| 48 | 
    mCamera= new float[3];  | 
|
| 49 | 
    mTouch = new float[3];  | 
|
| 50 | 
     | 
|
| 51 | 
    mPoint2D = new float[2];  | 
|
| 52 | 
    mMove2D = new float[2];  | 
|
| 53 | 
     | 
|
| 54 | 
    mRotAxis = rotAxis;  | 
|
| 55 | 
    mNumRotAxis = mRotAxis.length;  | 
|
| 56 | 
    mFaceAxis = faceAxis;  | 
|
| 57 | 
    mNumFaceAxis= mFaceAxis.length;  | 
|
| 58 | 
     | 
|
| 59 | 
    mNumFacesPerAxis = mNumFaceAxis / mNumRotAxis;  | 
|
| 60 | 
    mDistanceCenterFace3D = distance3D; // distance from the center of the object to each of its faces  | 
|
| 61 | 
    mDistanceCenterFace2D = distance2D; // distance from the center of a face to its edge  | 
|
| 62 | 
     | 
|
| 63 | 
        // mCastAxis[1][2]{0,1} are the 2D coords of the 2nd axis cast onto the face defined by the
   | 
|
| 64 | 
    // 1st pair (axis,lr)  | 
|
| 65 | 
    mCastAxis = new float[mNumFaceAxis][mNumRotAxis][2];  | 
|
| 66 | 
     | 
|
| 67 | 
    for( int casted=0; casted<mNumRotAxis; casted++)  | 
|
| 68 | 
          {
   | 
|
| 69 | 
    Static3D a = mRotAxis[casted];  | 
|
| 70 | 
    mPoint[0]= a.get0();  | 
|
| 71 | 
    mPoint[1]= a.get1();  | 
|
| 72 | 
    mPoint[2]= a.get2();  | 
|
| 73 | 
     | 
|
| 74 | 
    for( int surface=0; surface<mNumRotAxis; surface++)  | 
|
| 75 | 
    for(int lr=0; lr<mNumFacesPerAxis; lr++)  | 
|
| 76 | 
              {
   | 
|
| 77 | 
    int index = surface*mNumFacesPerAxis + lr;  | 
|
| 78 | 
     | 
|
| 79 | 
    if( casted!=surface )  | 
|
| 80 | 
                {
   | 
|
| 81 | 
    convertTo2Dcoords( mPoint, mRotAxis[surface], lr, mPoint2D);  | 
|
| 82 | 
    mCastAxis[index][casted][0] = mPoint2D[0];  | 
|
| 83 | 
    mCastAxis[index][casted][1] = mPoint2D[1];  | 
|
| 84 | 
    normalize2D(mCastAxis[index][casted]);  | 
|
| 85 | 
    }  | 
|
| 86 | 
    else  | 
|
| 87 | 
                {
   | 
|
| 88 | 
    mCastAxis[index][casted][0] = 0;  | 
|
| 89 | 
    mCastAxis[index][casted][1] = 0;  | 
|
| 90 | 
    }  | 
|
| 91 | 
    }  | 
|
| 92 | 
    }  | 
|
| 93 | 
    }  | 
|
| 94 | 
     | 
|
| 95 | 
    ///////////////////////////////////////////////////////////////////////////////////////////////////  | 
|
| 96 | 
     | 
|
| 97 | 
    private void normalize2D(float[] vect)  | 
|
| 98 | 
        {
   | 
|
| 99 | 
    float len = (float)Math.sqrt(vect[0]*vect[0] + vect[1]*vect[1]);  | 
|
| 100 | 
    vect[0] /= len;  | 
|
| 101 | 
    vect[1] /= len;  | 
|
| 102 | 
    }  | 
|
| 103 | 
     | 
|
| 104 | 
    ///////////////////////////////////////////////////////////////////////////////////////////////////  | 
|
| 105 | 
    // find the casted axis with which our move2D vector forms an angle closest to 90 deg.  | 
|
| 106 | 
     | 
|
| 107 | 
    private int computeRotationIndex(int axis, int lr, float[] move2D)  | 
|
| 108 | 
        {
   | 
|
| 109 | 
    float cosAngle, minCosAngle = Float.MAX_VALUE;  | 
|
| 110 | 
    int minIndex=-1;  | 
|
| 111 | 
    int index = axis*mNumFacesPerAxis + lr;  | 
|
| 112 | 
    float m0 = move2D[0];  | 
|
| 113 | 
    float m1 = move2D[1];  | 
|
| 114 | 
    float len = (float)Math.sqrt(m0*m0 + m1*m1);  | 
|
| 115 | 
     | 
|
| 116 | 
    if( len!=0.0f )  | 
|
| 117 | 
          {
   | 
|
| 118 | 
    m0 /= len;  | 
|
| 119 | 
    m1 /= len;  | 
|
| 120 | 
    }  | 
|
| 121 | 
    else  | 
|
| 122 | 
          {
   | 
|
| 123 | 
    m0 = 1.0f; // arbitrarily  | 
|
| 124 | 
    m1 = 0.0f; //  | 
|
| 125 | 
    }  | 
|
| 126 | 
     | 
|
| 127 | 
    for(int i=0; i<mNumRotAxis; i++)  | 
|
| 128 | 
          {
   | 
|
| 129 | 
    if( axis != i )  | 
|
| 130 | 
            {
   | 
|
| 131 | 
    cosAngle = m0*mCastAxis[index][i][0] + m1*mCastAxis[index][i][1];  | 
|
| 132 | 
    if( cosAngle<0 ) cosAngle = -cosAngle;  | 
|
| 133 | 
     | 
|
| 134 | 
    if( cosAngle<minCosAngle )  | 
|
| 135 | 
              {
   | 
|
| 136 | 
    minCosAngle=cosAngle;  | 
|
| 137 | 
    minIndex = i;  | 
|
| 138 | 
    }  | 
|
| 139 | 
    }  | 
|
| 140 | 
    }  | 
|
| 141 | 
     | 
|
| 142 | 
    return minIndex;  | 
|
| 143 | 
    }  | 
|
| 144 | 
     | 
|
| 145 | 
    ///////////////////////////////////////////////////////////////////////////////////////////////////  | 
|
| 146 | 
     | 
|
| 147 | 
    private float computeOffset(float[] point, float[] axis)  | 
|
| 148 | 
        {
   | 
|
| 149 | 
    return point[0]*axis[0] + point[1]*axis[1] + mDistanceCenterFace2D;  | 
|
| 150 | 
    }  | 
|
| 151 | 
     | 
|
| 152 | 
    ///////////////////////////////////////////////////////////////////////////////////////////////////  | 
|
| 153 | 
     | 
|
| 154 | 
    private boolean faceIsVisible(Static3D axis, int lr)  | 
|
| 155 | 
        {
   | 
|
| 156 | 
    float castCameraOnAxis = mCamera[0]*axis.get0() + mCamera[1]*axis.get1() + mCamera[2]*axis.get2();  | 
|
| 157 | 
    return (2*lr-1)*castCameraOnAxis > mDistanceCenterFace3D;  | 
|
| 158 | 
    }  | 
|
| 159 | 
     | 
|
| 160 | 
    ///////////////////////////////////////////////////////////////////////////////////////////////////  | 
|
| 161 | 
    // given precomputed mCamera and mPoint, respectively camera and touch point positions in ScreenSpace,  | 
|
| 162 | 
    // compute point 'output[]' which:  | 
|
| 163 | 
    // 1) lies on a face of the Object, i.e. surface defined by (axis, distance from (0,0,0)) [and this  | 
|
| 164 | 
    // distance is +-mDistanceCenterFace, depending if it is the face on the left or the right end of  | 
|
| 165 | 
    // the axis] (lr=0 or 1, so (2lr-1)*mDistanceCenterFace)  | 
|
| 166 | 
    // 2) is co-linear with mCamera and mPoint  | 
|
| 167 | 
    //  | 
|
| 168 | 
    // output = camera + alpha*(point-camera), where alpha = [dist-axis*camera] / [axis*(point-camera)]  | 
|
| 169 | 
     | 
|
| 170 | 
    private void castTouchPointOntoFace(Static3D axis, int lr, float[] output)  | 
|
| 171 | 
        {
   | 
|
| 172 | 
    float d0 = mPoint[0]-mCamera[0];  | 
|
| 173 | 
    float d1 = mPoint[1]-mCamera[1];  | 
|
| 174 | 
    float d2 = mPoint[2]-mCamera[2];  | 
|
| 175 | 
    float a0 = axis.get0();  | 
|
| 176 | 
    float a1 = axis.get1();  | 
|
| 177 | 
    float a2 = axis.get2();  | 
|
| 178 | 
     | 
|
| 179 | 
    float denom = a0*d0 + a1*d1 + a2*d2;  | 
|
| 180 | 
     | 
|
| 181 | 
    if( denom != 0.0f )  | 
|
| 182 | 
          {
   | 
|
| 183 | 
    float axisCam = a0*mCamera[0] + a1*mCamera[1] + a2*mCamera[2];  | 
|
| 184 | 
    float distance = (2*lr-1)*mDistanceCenterFace3D;  | 
|
| 185 | 
    float alpha = (distance-axisCam)/denom;  | 
|
| 186 | 
     | 
|
| 187 | 
    output[0] = mCamera[0] + d0*alpha;  | 
|
| 188 | 
    output[1] = mCamera[1] + d1*alpha;  | 
|
| 189 | 
    output[2] = mCamera[2] + d2*alpha;  | 
|
| 190 | 
    }  | 
|
| 191 | 
    }  | 
|
| 192 | 
     | 
|
| 193 | 
    ///////////////////////////////////////////////////////////////////////////////////////////////////  | 
|
| 194 | 
    // Convert the 3D point3D into a 2D point on the same face surface, but in a different  | 
|
| 195 | 
    // coordinate system: a in-plane 2D coord where the origin is in the point where the axis intersects  | 
|
| 196 | 
    // the surface, and whose Y axis points 'north' i.e. is in the plane given by the 3D origin, the  | 
|
| 197 | 
    // original 3D Y axis and our 2D in-plane origin.  | 
|
| 198 | 
    // If those 3 points constitute a degenerate triangle which does not define a plane - which can only  | 
|
| 199 | 
    // happen if axis is vertical (or in theory when 2D origin and 3D origin meet, but that would have to  | 
|
| 200 | 
    // mean that the distance between the center of the Object and its faces is 0) - then we arbitrarily  | 
|
| 201 | 
    // decide that 2D Y = (0,0,-1) in the North Pole and (0,0,1) in the South Pole)  | 
|
| 202 | 
     | 
|
| 203 | 
    private void convertTo2Dcoords(float[] point3D, Static3D axis, int lr, float[] output)  | 
|
| 204 | 
        {
   | 
|
| 205 | 
    float y0,y1,y2; // base Y vector of the 2D coord system  | 
|
| 206 | 
    float a0 = axis.get0();  | 
|
| 207 | 
    float a1 = axis.get1();  | 
|
| 208 | 
    float a2 = axis.get2();  | 
|
| 209 | 
     | 
|
| 210 | 
    if( lr==0 )  | 
|
| 211 | 
          {
   | 
|
| 212 | 
    a0=-a0; a1=-a1; a2=-a2;  | 
|
| 213 | 
    }  | 
|
| 214 | 
     | 
|
| 215 | 
    if( a0==0.0f && a2==0.0f )  | 
|
| 216 | 
          {
   | 
|
| 217 | 
    y0=0; y1=0; y2=-a1;  | 
|
| 218 | 
    }  | 
|
| 219 | 
    else if( a1==0.0f )  | 
|
| 220 | 
          {
   | 
|
| 221 | 
    y0=0; y1=1; y2=0;  | 
|
| 222 | 
    }  | 
|
| 223 | 
    else  | 
|
| 224 | 
          {
   | 
|
| 225 | 
    float norm = (float)(-a1/Math.sqrt(1-a1*a1));  | 
|
| 226 | 
    y0 = norm*a0; y1= norm*(a1-1/a1); y2=norm*a2;  | 
|
| 227 | 
    }  | 
|
| 228 | 
     | 
|
| 229 | 
    float x0 = y1*a2 - y2*a1; //  | 
|
| 230 | 
    float x1 = y2*a0 - y0*a2; // (2D coord baseY) x (axis) = 2D coord baseX  | 
|
| 231 | 
    float x2 = y0*a1 - y1*a0; //  | 
|
| 232 | 
     | 
|
| 233 | 
    float originAlpha = point3D[0]*a0 + point3D[1]*a1 + point3D[2]*a2;  | 
|
| 234 | 
     | 
|
| 235 | 
    float origin0 = originAlpha*a0; // coords of the point where axis  | 
|
| 236 | 
    float origin1 = originAlpha*a1; // intersects surface plane i.e.  | 
|
| 237 | 
    float origin2 = originAlpha*a2; // the origin of our 2D coord system  | 
|
| 238 | 
     | 
|
| 239 | 
    float v0 = point3D[0] - origin0;  | 
|
| 240 | 
    float v1 = point3D[1] - origin1;  | 
|
| 241 | 
    float v2 = point3D[2] - origin2;  | 
|
| 242 | 
     | 
|
| 243 | 
    output[0] = v0*x0 + v1*x1 + v2*x2;  | 
|
| 244 | 
    output[1] = v0*y0 + v1*y1 + v2*y2;  | 
|
| 245 | 
    }  | 
|
| 246 | 
     | 
|
| 247 | 
    ///////////////////////////////////////////////////////////////////////////////////////////////////  | 
|
| 248 | 
    // PUBLIC API  | 
|
| 249 | 
    ///////////////////////////////////////////////////////////////////////////////////////////////////  | 
|
| 250 | 
     | 
|
| 251 | 
    public boolean faceTouched(Static4D rotatedTouchPoint, Static4D rotatedCamera)  | 
|
| 252 | 
        {
   | 
|
| 253 | 
    float objectRatio = RubikObject.getObjectRatio();  | 
|
| 254 | 
     | 
|
| 255 | 
    mPoint[0] = rotatedTouchPoint.get0()/objectRatio;  | 
|
| 256 | 
    mPoint[1] = rotatedTouchPoint.get1()/objectRatio;  | 
|
| 257 | 
    mPoint[2] = rotatedTouchPoint.get2()/objectRatio;  | 
|
| 258 | 
     | 
|
| 259 | 
    mCamera[0] = rotatedCamera.get0()/objectRatio;  | 
|
| 260 | 
    mCamera[1] = rotatedCamera.get1()/objectRatio;  | 
|
| 261 | 
    mCamera[2] = rotatedCamera.get2()/objectRatio;  | 
|
| 262 | 
     | 
|
| 263 | 
    for( mLastTouchedAxis=0; mLastTouchedAxis<mNumRotAxis; mLastTouchedAxis++)  | 
|
| 264 | 
          {
   | 
|
| 265 | 
    for( mLastTouchedLR=0; mLastTouchedLR<mNumFacesPerAxis; mLastTouchedLR++)  | 
|
| 266 | 
            {
   | 
|
| 267 | 
    if( faceIsVisible(mRotAxis[mLastTouchedAxis], mLastTouchedLR) )  | 
|
| 268 | 
              {
   | 
|
| 269 | 
    castTouchPointOntoFace(mRotAxis[mLastTouchedAxis], mLastTouchedLR, mTouch);  | 
|
| 270 | 
    convertTo2Dcoords(mTouch, mRotAxis[mLastTouchedAxis], mLastTouchedLR, mPoint2D);  | 
|
| 271 | 
     | 
|
| 272 | 
    if( isInsideFace(mPoint2D) ) return true;  | 
|
| 273 | 
    }  | 
|
| 274 | 
    }  | 
|
| 275 | 
    }  | 
|
| 276 | 
     | 
|
| 277 | 
    return false;  | 
|
| 278 | 
    }  | 
|
| 279 | 
     | 
|
| 280 | 
    ///////////////////////////////////////////////////////////////////////////////////////////////////  | 
|
| 281 | 
     | 
|
| 282 | 
    public Static2D newRotation(Static4D rotatedTouchPoint)  | 
|
| 283 | 
        {
   | 
|
| 284 | 
    float objectRatio = RubikObject.getObjectRatio();  | 
|
| 285 | 
     | 
|
| 286 | 
    mPoint[0] = rotatedTouchPoint.get0()/objectRatio;  | 
|
| 287 | 
    mPoint[1] = rotatedTouchPoint.get1()/objectRatio;  | 
|
| 288 | 
    mPoint[2] = rotatedTouchPoint.get2()/objectRatio;  | 
|
| 289 | 
     | 
|
| 290 | 
    castTouchPointOntoFace(mRotAxis[mLastTouchedAxis], mLastTouchedLR, mTouch);  | 
|
| 291 | 
    convertTo2Dcoords(mTouch, mRotAxis[mLastTouchedAxis], mLastTouchedLR, mMove2D);  | 
|
| 292 | 
     | 
|
| 293 | 
    mMove2D[0] -= mPoint2D[0];  | 
|
| 294 | 
    mMove2D[1] -= mPoint2D[1];  | 
|
| 295 | 
     | 
|
| 296 | 
    int rotIndex = computeRotationIndex(mLastTouchedAxis, mLastTouchedLR, mMove2D);  | 
|
| 297 | 
    int index = mLastTouchedAxis*mNumFacesPerAxis+mLastTouchedLR;  | 
|
| 298 | 
    float offset = computeOffset(mPoint2D, mCastAxis[index][rotIndex]);  | 
|
| 299 | 
     | 
|
| 300 | 
    return new Static2D(rotIndex,offset);  | 
|
| 301 | 
    }  | 
|
| 302 | 
     | 
|
| 303 | 
    ///////////////////////////////////////////////////////////////////////////////////////////////////  | 
|
| 304 | 
     | 
|
| 305 | 
    public int getTouchedFace()  | 
|
| 306 | 
        {
   | 
|
| 307 | 
    return mNumFacesPerAxis==2 ? 2*mLastTouchedAxis + 1 - mLastTouchedLR : mLastTouchedAxis;  | 
|
| 308 | 
    }  | 
|
| 309 | 
     | 
|
| 310 | 
    ///////////////////////////////////////////////////////////////////////////////////////////////////  | 
|
| 311 | 
     | 
|
| 312 | 
    public float[] getTouchedPoint3D()  | 
|
| 313 | 
        {
   | 
|
| 314 | 
    return mTouch;  | 
|
| 315 | 
    }  | 
|
| 316 | 
    }  | 
|
| src/main/java/org/distorted/objects/RubikMovementPyraminx.java | ||
|---|---|---|
| 1 | 
    ///////////////////////////////////////////////////////////////////////////////////////////////////  | 
|
| 2 | 
    // Copyright 2020 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.objects;  | 
|
| 21 | 
     | 
|
| 22 | 
    ///////////////////////////////////////////////////////////////////////////////////////////////////  | 
|
| 23 | 
     | 
|
| 24 | 
    class RubikMovementPyraminx extends RubikMovementObject  | 
|
| 25 | 
    {
   | 
|
| 26 | 
    private static final float SQ6 = (float)Math.sqrt(6);  | 
|
| 27 | 
    private static final float SQ3 = (float)Math.sqrt(3);  | 
|
| 28 | 
     | 
|
| 29 | 
    ///////////////////////////////////////////////////////////////////////////////////////////////////  | 
|
| 30 | 
     | 
|
| 31 | 
    RubikMovementPyraminx()  | 
|
| 32 | 
        {
   | 
|
| 33 | 
    super(RubikPyraminx.ROT_AXIS, RubikPyraminx.FACE_AXIS, SQ6/12, SQ3/6);  | 
|
| 34 | 
    }  | 
|
| 35 | 
     | 
|
| 36 | 
    ///////////////////////////////////////////////////////////////////////////////////////////////////  | 
|
| 37 | 
     | 
|
| 38 | 
    boolean isInsideFace(float[] p)  | 
|
| 39 | 
        {
   | 
|
| 40 | 
    boolean a1 = p[1] >= -SQ3/6;  | 
|
| 41 | 
    boolean a2 = p[1] <= SQ3*(1.0f/3 + p[0]);  | 
|
| 42 | 
    boolean a3 = p[1] <= SQ3*(1.0f/3 - p[0]);  | 
|
| 43 | 
     | 
|
| 44 | 
    return a1 && a2 && a3;  | 
|
| 45 | 
    }  | 
|
| 46 | 
    }  | 
|
| src/main/java/org/distorted/objects/RubikObjectList.java | ||
|---|---|---|
| 42 | 42 | 
                           {5 , 24, R.raw.cube5, R.drawable.ui_small_cube5, R.drawable.ui_medium_cube5, R.drawable.ui_big_cube5, R.drawable.ui_huge_cube5}
   | 
| 43 | 43 | 
    },  | 
| 44 | 44 | 
    RubikCube.class,  | 
| 45 | 
             new RubikCubeMovement()
   | 
|
| 45 | 
             new RubikMovementCube()
   | 
|
| 46 | 46 | 
    ),  | 
| 47 | 47 | 
     | 
| 48 | 48 | 
    PYRA (  | 
| ... | ... | |
| 52 | 52 | 
                           {5 , 20, R.raw.pyra5, R.drawable.ui_small_pyra5, R.drawable.ui_medium_pyra5, R.drawable.ui_big_pyra5, R.drawable.ui_huge_pyra5}
   | 
| 53 | 53 | 
    },  | 
| 54 | 54 | 
    RubikPyraminx.class,  | 
| 55 | 
             new RubikPyraminxMovement()
   | 
|
| 55 | 
             new RubikMovementPyraminx()
   | 
|
| 56 | 56 | 
    ),  | 
| 57 | 57 | 
     | 
| 58 | 58 | 
    DINO (  | 
| ... | ... | |
| 60 | 60 | 
                           {3 , 10, R.raw.pyra3, R.drawable.ui_small_dino, R.drawable.ui_medium_dino, R.drawable.ui_big_dino, R.drawable.ui_huge_dino} ,
   | 
| 61 | 61 | 
    },  | 
| 62 | 62 | 
    RubikDino.class,  | 
| 63 | 
             new RubikDinoMovement()
   | 
|
| 63 | 
             new RubikMovementDino()
   | 
|
| 64 | 64 | 
    ),  | 
| 65 | 65 | 
    ;  | 
| 66 | 66 | 
     | 
| ... | ... | |
| 71 | 71 | 
     | 
| 72 | 72 | 
    private final int[] mObjectSizes, mMaxLevels, mSmallIconIDs, mMediumIconIDs, mBigIconIDs, mHugeIconIDs, mResourceIDs;  | 
| 73 | 73 | 
    private final Class<? extends RubikObject> mObjectClass;  | 
| 74 | 
      private final RubikObjectMovement mObjectMovementClass;
   | 
|
| 74 | 
      private final RubikMovementObject mObjectMovementClass;
   | 
|
| 75 | 75 | 
    private static final RubikObjectList[] objects;  | 
| 76 | 76 | 
    private static int mNumAll;  | 
| 77 | 77 | 
     | 
| ... | ... | |
| 283 | 283 | 
     | 
| 284 | 284 | 
    ///////////////////////////////////////////////////////////////////////////////////////////////////  | 
| 285 | 285 | 
     | 
| 286 | 
      RubikObjectList(int[][] info, Class<? extends RubikObject> object , RubikObjectMovement movement)
   | 
|
| 286 | 
      RubikObjectList(int[][] info, Class<? extends RubikObject> object , RubikMovementObject movement)
   | 
|
| 287 | 287 | 
        {
   | 
| 288 | 288 | 
    int length = info.length;  | 
| 289 | 289 | 
     | 
| ... | ... | |
| 373 | 373 | 
     | 
| 374 | 374 | 
    ///////////////////////////////////////////////////////////////////////////////////////////////////  | 
| 375 | 375 | 
     | 
| 376 | 
      public RubikObjectMovement getObjectMovementClass()
   | 
|
| 376 | 
      public RubikMovementObject getObjectMovementClass()
   | 
|
| 377 | 377 | 
        {
   | 
| 378 | 378 | 
    return mObjectMovementClass;  | 
| 379 | 379 | 
    }  | 
| src/main/java/org/distorted/objects/RubikObjectMovement.java | ||
|---|---|---|
| 1 | 
    ///////////////////////////////////////////////////////////////////////////////////////////////////  | 
|
| 2 | 
    // Copyright 2020 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.objects;  | 
|
| 21 | 
     | 
|
| 22 | 
    import org.distorted.library.type.Static2D;  | 
|
| 23 | 
    import org.distorted.library.type.Static3D;  | 
|
| 24 | 
    import org.distorted.library.type.Static4D;  | 
|
| 25 | 
     | 
|
| 26 | 
    ///////////////////////////////////////////////////////////////////////////////////////////////////  | 
|
| 27 | 
     | 
|
| 28 | 
    public abstract class RubikObjectMovement  | 
|
| 29 | 
      {
   | 
|
| 30 | 
    private int mLastTouchedAxis;  | 
|
| 31 | 
    private float[] mPoint, mCamera, mTouch;  | 
|
| 32 | 
    private float[] mPoint2D, mMove2D;  | 
|
| 33 | 
    private float[][][] mCastAxis;  | 
|
| 34 | 
    private int mLastTouchedLR;  | 
|
| 35 | 
    private int mNumAxis, mNumFacesPerAxis;  | 
|
| 36 | 
    private float mDistanceCenterFace3D, mDistanceCenterFace2D;  | 
|
| 37 | 
    private Static3D[] mAxis;  | 
|
| 38 | 
     | 
|
| 39 | 
    ///////////////////////////////////////////////////////////////////////////////////////////////////  | 
|
| 40 | 
     | 
|
| 41 | 
    abstract boolean isInsideFace(float[] point);  | 
|
| 42 | 
     | 
|
| 43 | 
    ///////////////////////////////////////////////////////////////////////////////////////////////////  | 
|
| 44 | 
     | 
|
| 45 | 
    RubikObjectMovement(Static3D[] axis, float numFacesPerAxis, float distance3D, float distance2D)  | 
|
| 46 | 
        {
   | 
|
| 47 | 
    mPoint = new float[3];  | 
|
| 48 | 
    mCamera= new float[3];  | 
|
| 49 | 
    mTouch = new float[3];  | 
|
| 50 | 
     | 
|
| 51 | 
    mPoint2D = new float[2];  | 
|
| 52 | 
    mMove2D = new float[2];  | 
|
| 53 | 
     | 
|
| 54 | 
    mAxis = axis;  | 
|
| 55 | 
    mNumAxis = mAxis.length;  | 
|
| 56 | 
    mNumFacesPerAxis = (int)numFacesPerAxis; // TODO  | 
|
| 57 | 
    mDistanceCenterFace3D = distance3D; // distance from the center of the object to each of its faces  | 
|
| 58 | 
    mDistanceCenterFace2D = distance2D; // distance from the center of a face to its edge  | 
|
| 59 | 
     | 
|
| 60 | 
        // mCastAxis[1][2]{0,1} are the 2D coords of the 2nd axis cast onto the face defined by the
   | 
|
| 61 | 
    // 1st pair (axis,lr)  | 
|
| 62 | 
    mCastAxis = new float[mNumAxis*mNumFacesPerAxis][mNumAxis][2];  | 
|
| 63 | 
     | 
|
| 64 | 
    for( int casted=0; casted<mNumAxis; casted++)  | 
|
| 65 | 
          {
   | 
|
| 66 | 
    Static3D a = mAxis[casted];  | 
|
| 67 | 
    mPoint[0]= a.get0();  | 
|
| 68 | 
    mPoint[1]= a.get1();  | 
|
| 69 | 
    mPoint[2]= a.get2();  | 
|
| 70 | 
     | 
|
| 71 | 
    for( int surface=0; surface<mNumAxis; surface++)  | 
|
| 72 | 
    for(int lr=0; lr<mNumFacesPerAxis; lr++)  | 
|
| 73 | 
              {
   | 
|
| 74 | 
    int index = surface*mNumFacesPerAxis + lr;  | 
|
| 75 | 
     | 
|
| 76 | 
    if( casted!=surface )  | 
|
| 77 | 
                {
   | 
|
| 78 | 
    convertTo2Dcoords( mPoint, mAxis[surface], lr, mPoint2D);  | 
|
| 79 | 
    mCastAxis[index][casted][0] = mPoint2D[0];  | 
|
| 80 | 
    mCastAxis[index][casted][1] = mPoint2D[1];  | 
|
| 81 | 
    normalize2D(mCastAxis[index][casted]);  | 
|
| 82 | 
    }  | 
|
| 83 | 
    else  | 
|
| 84 | 
                {
   | 
|
| 85 | 
    mCastAxis[index][casted][0] = 0;  | 
|
| 86 | 
    mCastAxis[index][casted][1] = 0;  | 
|
| 87 | 
    }  | 
|
| 88 | 
    }  | 
|
| 89 | 
    }  | 
|
| 90 | 
    }  | 
|
| 91 | 
     | 
|
| 92 | 
    ///////////////////////////////////////////////////////////////////////////////////////////////////  | 
|
| 93 | 
     | 
|
| 94 | 
    private void normalize2D(float[] vect)  | 
|
| 95 | 
        {
   | 
|
| 96 | 
    float len = (float)Math.sqrt(vect[0]*vect[0] + vect[1]*vect[1]);  | 
|
| 97 | 
    vect[0] /= len;  | 
|
| 98 | 
    vect[1] /= len;  | 
|
| 99 | 
    }  | 
|
| 100 | 
     | 
|
| 101 | 
    ///////////////////////////////////////////////////////////////////////////////////////////////////  | 
|
| 102 | 
    // find the casted axis with which our move2D vector forms an angle closest to 90 deg.  | 
|
| 103 | 
     | 
|
| 104 | 
    private int computeRotationIndex(int axis, int lr, float[] move2D)  | 
|
| 105 | 
        {
   | 
|
| 106 | 
    float cosAngle, minCosAngle = Float.MAX_VALUE;  | 
|
| 107 | 
    int minIndex=-1;  | 
|
| 108 | 
    int index = axis*mNumFacesPerAxis + lr;  | 
|
| 109 | 
    float m0 = move2D[0];  | 
|
| 110 | 
    float m1 = move2D[1];  | 
|
| 111 | 
    float len = (float)Math.sqrt(m0*m0 + m1*m1);  | 
|
| 112 | 
     | 
|
| 113 | 
    if( len!=0.0f )  | 
|
| 114 | 
          {
   | 
|
| 115 | 
    m0 /= len;  | 
|
| 116 | 
    m1 /= len;  | 
|
| 117 | 
    }  | 
|
| 118 | 
    else  | 
|
| 119 | 
          {
   | 
|
| 120 | 
    m0 = 1.0f; // arbitrarily  | 
|
| 121 | 
    m1 = 0.0f; //  | 
|
| 122 | 
    }  | 
|
| 123 | 
     | 
|
| 124 | 
    for(int i=0; i<mNumAxis; i++)  | 
|
| 125 | 
          {
   | 
|
| 126 | 
    if( axis != i )  | 
|
| 127 | 
            {
   | 
|
| 128 | 
    cosAngle = m0*mCastAxis[index][i][0] + m1*mCastAxis[index][i][1];  | 
|
| 129 | 
    if( cosAngle<0 ) cosAngle = -cosAngle;  | 
|
| 130 | 
     | 
|
| 131 | 
    if( cosAngle<minCosAngle )  | 
|
| 132 | 
              {
   | 
|
| 133 | 
    minCosAngle=cosAngle;  | 
|
| 134 | 
    minIndex = i;  | 
|
| 135 | 
    }  | 
|
| 136 | 
    }  | 
|
| 137 | 
    }  | 
|
| 138 | 
     | 
|
| 139 | 
    return minIndex;  | 
|
| 140 | 
    }  | 
|
| 141 | 
     | 
|
| 142 | 
    ///////////////////////////////////////////////////////////////////////////////////////////////////  | 
|
| 143 | 
     | 
|
| 144 | 
    private float computeOffset(float[] point, float[] axis)  | 
|
| 145 | 
        {
   | 
|
| 146 | 
    return point[0]*axis[0] + point[1]*axis[1] + mDistanceCenterFace2D;  | 
|
| 147 | 
    }  | 
|
| 148 | 
     | 
|
| 149 | 
    ///////////////////////////////////////////////////////////////////////////////////////////////////  | 
|
| 150 | 
     | 
|
| 151 | 
    private boolean faceIsVisible(Static3D axis, int lr)  | 
|
| 152 | 
        {
   | 
|
| 153 | 
    float castCameraOnAxis = mCamera[0]*axis.get0() + mCamera[1]*axis.get1() + mCamera[2]*axis.get2();  | 
|
| 154 | 
    return (2*lr-1)*castCameraOnAxis > mDistanceCenterFace3D;  | 
|
| 155 | 
    }  | 
|
| 156 | 
     | 
|
| 157 | 
    ///////////////////////////////////////////////////////////////////////////////////////////////////  | 
|
| 158 | 
    // given precomputed mCamera and mPoint, respectively camera and touch point positions in ScreenSpace,  | 
|
| 159 | 
    // compute point 'output[]' which:  | 
|
| 160 | 
    // 1) lies on a face of the Object, i.e. surface defined by (axis, distance from (0,0,0)) [and this  | 
|
| 161 | 
    // distance is +-mDistanceCenterFace, depending if it is the face on the left or the right end of  | 
|
| 162 | 
    // the axis] (lr=0 or 1, so (2lr-1)*mDistanceCenterFace)  | 
|
| 163 | 
    // 2) is co-linear with mCamera and mPoint  | 
|
| 164 | 
    //  | 
|
| 165 | 
    // output = camera + alpha*(point-camera), where alpha = [dist-axis*camera] / [axis*(point-camera)]  | 
|
| 166 | 
     | 
|
| 167 | 
    private void castTouchPointOntoFace(Static3D axis, int lr, float[] output)  | 
|
| 168 | 
        {
   | 
|
| 169 | 
    float d0 = mPoint[0]-mCamera[0];  | 
|
| 170 | 
    float d1 = mPoint[1]-mCamera[1];  | 
|
| 171 | 
    float d2 = mPoint[2]-mCamera[2];  | 
|
| 172 | 
    float a0 = axis.get0();  | 
|
| 173 | 
    float a1 = axis.get1();  | 
|
| 174 | 
    float a2 = axis.get2();  | 
|
| 175 | 
     | 
|
| 176 | 
    float denom = a0*d0 + a1*d1 + a2*d2;  | 
|
| 177 | 
     | 
|
| 178 | 
    if( denom != 0.0f )  | 
|
| 179 | 
          {
   | 
|
| 180 | 
    float axisCam = a0*mCamera[0] + a1*mCamera[1] + a2*mCamera[2];  | 
|
| 181 | 
    float distance = (2*lr-1)*mDistanceCenterFace3D;  | 
|
| 182 | 
    float alpha = (distance-axisCam)/denom;  | 
|
| 183 | 
     | 
|
| 184 | 
    output[0] = mCamera[0] + d0*alpha;  | 
|
| 185 | 
    output[1] = mCamera[1] + d1*alpha;  | 
|
| 186 | 
    output[2] = mCamera[2] + d2*alpha;  | 
|
| 187 | 
    }  | 
|
| 188 | 
    }  | 
|
| 189 | 
     | 
|
| 190 | 
    ///////////////////////////////////////////////////////////////////////////////////////////////////  | 
|
| 191 | 
    // Convert the 3D point3D into a 2D point on the same face surface, but in a different  | 
|
| 192 | 
    // coordinate system: a in-plane 2D coord where the origin is in the point where the axis intersects  | 
|
| 193 | 
    // the surface, and whose Y axis points 'north' i.e. is in the plane given by the 3D origin, the  | 
|
| 194 | 
    // original 3D Y axis and our 2D in-plane origin.  | 
|
| 195 | 
    // If those 3 points constitute a degenerate triangle which does not define a plane - which can only  | 
|
| 196 | 
    // happen if axis is vertical (or in theory when 2D origin and 3D origin meet, but that would have to  | 
|
| 197 | 
    // mean that the distance between the center of the Object and its faces is 0) - then we arbitrarily  | 
|
| 198 | 
    // decide that 2D Y = (0,0,-1) in the North Pole and (0,0,1) in the South Pole)  | 
|
| 199 | 
     | 
|
| 200 | 
    private void convertTo2Dcoords(float[] point3D, Static3D axis, int lr, float[] output)  | 
|
| 201 | 
        {
   | 
|
| 202 | 
    float y0,y1,y2; // base Y vector of the 2D coord system  | 
|
| 203 | 
    float a0 = axis.get0();  | 
|
| 204 | 
    float a1 = axis.get1();  | 
|
| 205 | 
    float a2 = axis.get2();  | 
|
| 206 | 
     | 
|
| 207 | 
    if( lr==0 )  | 
|
| 208 | 
          {
   | 
|
| 209 | 
    a0=-a0; a1=-a1; a2=-a2;  | 
|
| 210 | 
    }  | 
|
| 211 | 
     | 
|
| 212 | 
    if( a0==0.0f && a2==0.0f )  | 
|
| 213 | 
          {
   | 
|
| 214 | 
    y0=0; y1=0; y2=-a1;  | 
|
| 215 | 
    }  | 
|
| 216 | 
    else if( a1==0.0f )  | 
|
| 217 | 
          {
   | 
|
| 218 | 
    y0=0; y1=1; y2=0;  | 
|
| 219 | 
    }  | 
|
| 220 | 
    else  | 
|
| 221 | 
          {
   | 
|
| 222 | 
    float norm = (float)(-a1/Math.sqrt(1-a1*a1));  | 
|
| 223 | 
    y0 = norm*a0; y1= norm*(a1-1/a1); y2=norm*a2;  | 
|
| 224 | 
    }  | 
|
| 225 | 
     | 
|
| 226 | 
    float x0 = y1*a2 - y2*a1; //  | 
|
| 227 | 
    float x1 = y2*a0 - y0*a2; // (2D coord baseY) x (axis) = 2D coord baseX  | 
|
| 228 | 
    float x2 = y0*a1 - y1*a0; //  | 
|
| 229 | 
     | 
|
| 230 | 
    float originAlpha = point3D[0]*a0 + point3D[1]*a1 + point3D[2]*a2;  | 
|
| 231 | 
     | 
|
| 232 | 
    float origin0 = originAlpha*a0; // coords of the point where axis  | 
|
| 233 | 
    float origin1 = originAlpha*a1; // intersects surface plane i.e.  | 
|
| 234 | 
    float origin2 = originAlpha*a2; // the origin of our 2D coord system  | 
|
| 235 | 
     | 
|
| 236 | 
    float v0 = point3D[0] - origin0;  | 
|
| 237 | 
    float v1 = point3D[1] - origin1;  | 
|
| 238 | 
    float v2 = point3D[2] - origin2;  | 
|
| 239 | 
     | 
|
| 240 | 
    output[0] = v0*x0 + v1*x1 + v2*x2;  | 
|
| 241 | 
    output[1] = v0*y0 + v1*y1 + v2*y2;  | 
|
| 242 | 
    }  | 
|
| 243 | 
     | 
|
| 244 | 
    ///////////////////////////////////////////////////////////////////////////////////////////////////  | 
|
| 245 | 
    // PUBLIC API  | 
|
| 246 | 
    ///////////////////////////////////////////////////////////////////////////////////////////////////  | 
|
| 247 | 
     | 
|
| 248 | 
    public boolean faceTouched(Static4D rotatedTouchPoint, Static4D rotatedCamera)  | 
|
| 249 | 
        {
   | 
|
| 250 | 
    float objectRatio = RubikObject.getObjectRatio();  | 
|
| 251 | 
     | 
|
| 252 | 
    mPoint[0] = rotatedTouchPoint.get0()/objectRatio;  | 
|
| 253 | 
    mPoint[1] = rotatedTouchPoint.get1()/objectRatio;  | 
|
| 254 | 
    mPoint[2] = rotatedTouchPoint.get2()/objectRatio;  | 
|
| 255 | 
     | 
|
| 256 | 
    mCamera[0] = rotatedCamera.get0()/objectRatio;  | 
|
| 257 | 
    mCamera[1] = rotatedCamera.get1()/objectRatio;  | 
|
| 258 | 
    mCamera[2] = rotatedCamera.get2()/objectRatio;  | 
|
| 259 | 
     | 
|
| 260 | 
    for( mLastTouchedAxis=0; mLastTouchedAxis<mNumAxis; mLastTouchedAxis++)  | 
|
| 261 | 
          {
   | 
|
| 262 | 
    for( mLastTouchedLR=0; mLastTouchedLR<mNumFacesPerAxis; mLastTouchedLR++)  | 
|
| 263 | 
            {
   | 
|
| 264 | 
    if( faceIsVisible(mAxis[mLastTouchedAxis], mLastTouchedLR) )  | 
|
| 265 | 
              {
   | 
|
| 266 | 
    castTouchPointOntoFace(mAxis[mLastTouchedAxis], mLastTouchedLR, mTouch);  | 
|
| 267 | 
    convertTo2Dcoords(mTouch, mAxis[mLastTouchedAxis], mLastTouchedLR, mPoint2D);  | 
|
| 268 | 
     | 
|
| 269 | 
    if( isInsideFace(mPoint2D) ) return true;  | 
|
| 270 | 
    }  | 
|
| 271 | 
    }  | 
|
| 272 | 
    }  | 
|
| 273 | 
     | 
|
| 274 | 
    return false;  | 
|
| 275 | 
    }  | 
|
| 276 | 
     | 
|
| 277 | 
    ///////////////////////////////////////////////////////////////////////////////////////////////////  | 
|
| 278 | 
     | 
|
| 279 | 
    public Static2D newRotation(Static4D rotatedTouchPoint)  | 
|
| 280 | 
        {
   | 
|
| 281 | 
    float objectRatio = RubikObject.getObjectRatio();  | 
|
| 282 | 
     | 
|
| 283 | 
    mPoint[0] = rotatedTouchPoint.get0()/objectRatio;  | 
|
| 284 | 
    mPoint[1] = rotatedTouchPoint.get1()/objectRatio;  | 
|
| 285 | 
    mPoint[2] = rotatedTouchPoint.get2()/objectRatio;  | 
|
| 286 | 
     | 
|
| 287 | 
    castTouchPointOntoFace(mAxis[mLastTouchedAxis], mLastTouchedLR, mTouch);  | 
|
| 288 | 
    convertTo2Dcoords(mTouch, mAxis[mLastTouchedAxis], mLastTouchedLR, mMove2D);  | 
|
| 289 | 
     | 
|
| 290 | 
    mMove2D[0] -= mPoint2D[0];  | 
|
| 291 | 
    mMove2D[1] -= mPoint2D[1];  | 
|
| 292 | 
     | 
|
| 293 | 
    int rotIndex = computeRotationIndex(mLastTouchedAxis, mLastTouchedLR, mMove2D);  | 
|
| 294 | 
    int index = mLastTouchedAxis*mNumFacesPerAxis+mLastTouchedLR;  | 
|
| 295 | 
    float offset = computeOffset(mPoint2D, mCastAxis[index][rotIndex]);  | 
|
| 296 | 
     | 
|
| 297 | 
    return new Static2D(rotIndex,offset);  | 
|
| 298 | 
    }  | 
|
| 299 | 
     | 
|
| 300 | 
    ///////////////////////////////////////////////////////////////////////////////////////////////////  | 
|
| 301 | 
     | 
|
| 302 | 
    public int getTouchedFace()  | 
|
| 303 | 
        {
   | 
|
| 304 | 
    return mNumFacesPerAxis==2 ? 2*mLastTouchedAxis + 1 - mLastTouchedLR : mLastTouchedAxis;  | 
|
| 305 | 
    }  | 
|
| 306 | 
     | 
|
| 307 | 
    ///////////////////////////////////////////////////////////////////////////////////////////////////  | 
|
| 308 | 
     | 
|
| 309 | 
    public float[] getTouchedPoint3D()  | 
|
| 310 | 
        {
   | 
|
| 311 | 
    return mTouch;  | 
|
| 312 | 
    }  | 
|
| 313 | 
    }  | 
|
| src/main/java/org/distorted/objects/RubikPyraminx.java | ||
|---|---|---|
| 46 | 46 | 
    private static final float SQ3 = (float)Math.sqrt(3);  | 
| 47 | 47 | 
    private static final float SQ6 = (float)Math.sqrt(6);  | 
| 48 | 48 | 
     | 
| 49 | 
    static final Static3D[] AXIS = new Static3D[]  | 
|
| 49 | 
      static final Static3D[] ROT_AXIS = new Static3D[]
   | 
|
| 50 | 50 | 
             {
   | 
| 51 | 51 | 
    new Static3D( 0, 1, 0 ),  | 
| 52 | 52 | 
    new Static3D( 0, -1.0f/3, 2*SQ2/3 ),  | 
| ... | ... | |
| 54 | 54 | 
    new Static3D( SQ2*SQ3/3, -1.0f/3, -SQ2/3 )  | 
| 55 | 55 | 
    };  | 
| 56 | 56 | 
     | 
| 57 | 
    static final Static3D[] FACE_AXIS = new Static3D[]  | 
|
| 58 | 
             {
   | 
|
| 59 | 
    new Static3D( 0, -1, 0 ),  | 
|
| 60 | 
    new Static3D( 0, 1.0f/3,-2*SQ2/3 ),  | 
|
| 61 | 
    new Static3D( SQ2*SQ3/3, 1.0f/3, SQ2/3 ),  | 
|
| 62 | 
    new Static3D(-SQ2*SQ3/3, 1.0f/3, SQ2/3 )  | 
|
| 63 | 
    };  | 
|
| 64 | 
     | 
|
| 57 | 65 | 
    private static final int[] FACE_COLORS = new int[]  | 
| 58 | 66 | 
             {
   | 
| 59 | 
               0xff00ff00, 0xffffff00,  // AXIS[0]right (GREEN ) AXIS[1]right (YELLOW )
   | 
|
| 60 | 
               0xff0000ff, 0xffff0000   // AXIS[2]right (BLUE  ) AXIS[3]right (RED    )
   | 
|
| 67 | 
               0xff00ff00, 0xffffff00,  // FACE_AXIS[0] (GREEN ) FACE_AXIS[1] (YELLOW )
   | 
|
| 68 | 
               0xff0000ff, 0xffff0000   // FACE_AXIS[2] (BLUE  ) FACE_AXIS[3] (RED    )
   | 
|
| 61 | 69 | 
    };  | 
| 62 | 70 | 
     | 
| 63 | 71 | 
    // computed with res/raw/compute_quats.c  | 
| ... | ... | |
| 81 | 89 | 
    private static VertexEffectRotate[] ROTATION;  | 
| 82 | 90 | 
     | 
| 83 | 91 | 
    private static MeshBase mMesh =null;  | 
| 84 | 
    private static MeshBase[] mMeshRotated = new MeshBase[AXIS.length];  | 
|
| 92 | 
      private static MeshBase[] mMeshRotated = new MeshBase[ROT_AXIS.length];
   | 
|
| 85 | 93 | 
     | 
| 86 | 94 | 
    static  | 
| 87 | 95 | 
        {
   | 
| 88 | 96 | 
    Static3D center = new Static3D(0,0,0);  | 
| 89 | 97 | 
    Static1D angle = new Static1D(180.0f);  | 
| 90 | 98 | 
     | 
| 91 | 
    ROTATION = new VertexEffectRotate[AXIS.length];  | 
|
| 99 | 
        ROTATION = new VertexEffectRotate[ROT_AXIS.length];
   | 
|
| 92 | 100 | 
     | 
| 93 | 
        for(int i=0; i<AXIS.length; i++)
   | 
|
| 101 | 
        for(int i = 0; i< ROT_AXIS.length; i++)
   | 
|
| 94 | 102 | 
          {
   | 
| 95 | 
    ROTATION[i] = new VertexEffectRotate( angle, AXIS[i], center);  | 
|
| 103 | 
          ROTATION[i] = new VertexEffectRotate( angle, ROT_AXIS[i], center);
   | 
|
| 96 | 104 | 
    mMeshRotated[i] = null;  | 
| 97 | 105 | 
    }  | 
| 98 | 106 | 
    }  | 
| ... | ... | |
| 388 | 396 | 
     | 
| 389 | 397 | 
    public Static3D[] getRotationAxis()  | 
| 390 | 398 | 
        {
   | 
| 391 | 
    return AXIS;  | 
|
| 399 | 
        return ROT_AXIS;
   | 
|
| 392 | 400 | 
    }  | 
| 393 | 401 | 
     | 
| 394 | 402 | 
    ///////////////////////////////////////////////////////////////////////////////////////////////////  | 
| src/main/java/org/distorted/objects/RubikPyraminxMovement.java | ||
|---|---|---|
| 1 | 
    ///////////////////////////////////////////////////////////////////////////////////////////////////  | 
|
| 2 | 
    // Copyright 2020 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.objects;  | 
|
| 21 | 
     | 
|
| 22 | 
    ///////////////////////////////////////////////////////////////////////////////////////////////////  | 
|
| 23 | 
     | 
|
| 24 | 
    class RubikPyraminxMovement extends RubikObjectMovement  | 
|
| 25 | 
    {
   | 
|
| 26 | 
    private static final float SQ6 = (float)Math.sqrt(6);  | 
|
| 27 | 
    private static final float SQ3 = (float)Math.sqrt(3);  | 
|
| 28 | 
     | 
|
| 29 | 
    ///////////////////////////////////////////////////////////////////////////////////////////////////  | 
|
| 30 | 
     | 
|
| 31 | 
    RubikPyraminxMovement()  | 
|
| 32 | 
        {
   | 
|
| 33 | 
    super(RubikPyraminx.AXIS, 1, SQ6/12, SQ3/6);  | 
|
| 34 | 
    }  | 
|
| 35 | 
     | 
|
| 36 | 
    ///////////////////////////////////////////////////////////////////////////////////////////////////  | 
|
| 37 | 
     | 
|
| 38 | 
    boolean isInsideFace(float[] p)  | 
|
| 39 | 
        {
   | 
|
| 40 | 
    boolean a1 = p[1] >= -SQ3/6;  | 
|
| 41 | 
    boolean a2 = p[1] <= SQ3*(1.0f/3 + p[0]);  | 
|
| 42 | 
    boolean a3 = p[1] <= SQ3*(1.0f/3 - p[0]);  | 
|
| 43 | 
     | 
|
| 44 | 
    return a1 && a2 && a3;  | 
|
| 45 | 
    }  | 
|
| 46 | 
    }  | 
|
Also available in: Unified diff
Introduce separate ROT_AXIS and FACE_AXIS ( step 1 )