Project

General

Profile

Download (8.82 KB) Statistics
| Branch: | Tag: | Revision:

magiccube / src / main / java / org / distorted / object / RubikCubeMovement.java @ efef689c

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.object;
21

    
22
import org.distorted.library.type.Static2D;
23
import org.distorted.library.type.Static4D;
24

    
25
///////////////////////////////////////////////////////////////////////////////////////////////////
26

    
27
class RubikCubeMovement extends RubikObjectMovement
28
{
29
    private final static int NONE   =-1;
30
    private final static int FRONT  = 0;  //
31
    private final static int BACK   = 1;  //
32
    private final static int LEFT   = 2;  // has to be 6 consecutive ints
33
    private final static int RIGHT  = 3;  // FRONT ... BOTTOM
34
    private final static int TOP    = 4;  //
35
    private final static int BOTTOM = 5;  //
36

    
37
    private static final int VECTX  = 0;  //
38
    private static final int VECTY  = 1;  // don't change this
39
    private static final int VECTZ  = 2;  //
40

    
41
    private static final int[] VECT = {VECTX,VECTY,VECTZ};
42

    
43
    private float[] mPoint, mCamera, mDiff, mTouch;
44
    private int mRotationVect, mLastTouchedFace;
45

    
46
///////////////////////////////////////////////////////////////////////////////////////////////////
47

    
48
    private boolean isVertical(float x, float y)
49
      {
50
      return (y>x) ? (y>=-x) : (y< -x);
51
      }
52

    
53
///////////////////////////////////////////////////////////////////////////////////////////////////
54

    
55
    private int retFaceSign(int face)
56
      {
57
      return (face==FRONT || face==RIGHT || face==TOP) ? 1:-1;
58
      }
59

    
60
///////////////////////////////////////////////////////////////////////////////////////////////////
61

    
62
    private int retFaceRotationSign(int face)
63
      {
64
      return (face==BACK || face==RIGHT || face==TOP) ? 1:-1;
65
      }
66

    
67
///////////////////////////////////////////////////////////////////////////////////////////////////
68
// retFace{X,Y,Z}axis: 3 functions which return which real AXIS gets mapped to which when we look
69
// directly at a given face. For example, when we look at the RIGHT face of the cube (with TOP still
70
// in the top) then the 'real' X axis becomes the 'Z' axis, thus retFaceXaxis(RIGHT) = VECTZ.
71

    
72
    private int retFaceXaxis(int face)
73
      {
74
      switch(face)
75
        {
76
        case FRONT :
77
        case BACK  : return VECTX;
78
        case LEFT  :
79
        case RIGHT : return VECTZ;
80
        case TOP   :
81
        case BOTTOM: return VECTX;
82
        }
83

    
84
      return -1;
85
      }
86

    
87
///////////////////////////////////////////////////////////////////////////////////////////////////
88

    
89
    private int retFaceYaxis(int face)
90
      {
91
      switch(face)
92
        {
93
        case FRONT :
94
        case BACK  : return VECTY;
95
        case LEFT  :
96
        case RIGHT : return VECTY;
97
        case TOP   :
98
        case BOTTOM: return VECTZ;
99
        }
100

    
101
      return -1;
102
      }
103

    
104
///////////////////////////////////////////////////////////////////////////////////////////////////
105

    
106
    private int retFaceZaxis(int face)
107
      {
108
      switch(face)
109
        {
110
        case FRONT :
111
        case BACK  : return VECTZ;
112
        case LEFT  :
113
        case RIGHT : return VECTX;
114
        case TOP   :
115
        case BOTTOM: return VECTY;
116
        }
117

    
118
      return -1;
119
      }
120

    
121
///////////////////////////////////////////////////////////////////////////////////////////////////
122

    
123
    private boolean faceIsVisible(int face, float cubeHalfSize)
124
      {
125
      int sign = retFaceSign(face);
126
      int zAxis= retFaceZaxis(face);
127

    
128
      return sign*mCamera[zAxis] > cubeHalfSize;
129
      }
130

    
131
///////////////////////////////////////////////////////////////////////////////////////////////////
132
// given precomputed mCamera and mPoint, respectively camera and touch point positions in ScreenSpace,
133
// cast this touch point onto the surface defined by the 'face' and write the cast coords to 'output'.
134
// Center of the 'face' = (0,0), third coord always +- cubeHalfSize.
135

    
136
    private void castTouchPointOntoFace(int face, float cubeHalfSize, float[] output)
137
      {
138
      int sign = retFaceSign(face);
139
      int zAxis= retFaceZaxis(face);
140
      float diff = mPoint[zAxis]-mCamera[zAxis];
141

    
142
      float ratio =  diff!=0.0f ? (sign*cubeHalfSize-mCamera[zAxis])/diff : 0.0f;
143

    
144
      output[0] = (mPoint[0]-mCamera[0])*ratio + mCamera[0];
145
      output[1] = (mPoint[1]-mCamera[1])*ratio + mCamera[1];
146
      output[2] = (mPoint[2]-mCamera[2])*ratio + mCamera[2];
147
      }
148

    
149
///////////////////////////////////////////////////////////////////////////////////////////////////
150

    
151
    RubikCubeMovement()
152
      {
153
      mPoint = new float[3];
154
      mCamera= new float[3];
155
      mDiff  = new float[3];
156
      mTouch = new float[3];
157
      }
158

    
159
///////////////////////////////////////////////////////////////////////////////////////////////////
160
// PUBLIC API
161
///////////////////////////////////////////////////////////////////////////////////////////////////
162

    
163
    public boolean faceTouched(Static4D rotatedTouchPoint, Static4D rotatedCamera)
164
      {
165
      float cubeHalfSize= RubikObject.OBJECT_SCREEN_RATIO*0.5f;
166

    
167
      mPoint[0]  = rotatedTouchPoint.get0();
168
      mPoint[1]  = rotatedTouchPoint.get1();
169
      mPoint[2]  = rotatedTouchPoint.get2();
170

    
171
      mCamera[0] = rotatedCamera.get0();
172
      mCamera[1] = rotatedCamera.get1();
173
      mCamera[2] = rotatedCamera.get2();
174

    
175
      for( mLastTouchedFace=FRONT; mLastTouchedFace<=BOTTOM; mLastTouchedFace++)
176
        {
177
        if( faceIsVisible(mLastTouchedFace,cubeHalfSize) )
178
          {
179
          castTouchPointOntoFace(mLastTouchedFace,cubeHalfSize, mTouch);
180

    
181
          float qX= (mTouch[0]+cubeHalfSize) / (2*cubeHalfSize);
182
          float qY= (mTouch[1]+cubeHalfSize) / (2*cubeHalfSize);
183
          float qZ= (mTouch[2]+cubeHalfSize) / (2*cubeHalfSize);
184

    
185
          if( qX<=1 && qX>=0 && qY<=1 && qY>=0 && qZ<=1 && qZ>=0 ) return true;
186
          }
187
        }
188

    
189
      mLastTouchedFace = NONE;
190
      return false;
191
      }
192

    
193
///////////////////////////////////////////////////////////////////////////////////////////////////
194

    
195
    public Static2D newRotation(Static4D rotatedTouchPoint)
196
      {
197
      float cubeHalfSize= RubikObject.OBJECT_SCREEN_RATIO*0.5f;
198

    
199
      mPoint[0] = rotatedTouchPoint.get0();
200
      mPoint[1] = rotatedTouchPoint.get1();
201
      mPoint[2] = rotatedTouchPoint.get2();
202

    
203
      castTouchPointOntoFace(mLastTouchedFace,cubeHalfSize,mDiff);
204

    
205
      mDiff[0] -= mTouch[0];
206
      mDiff[1] -= mTouch[1];
207
      mDiff[2] -= mTouch[2];
208

    
209
      int xAxis = retFaceXaxis(mLastTouchedFace);
210
      int yAxis = retFaceYaxis(mLastTouchedFace);
211
      mRotationVect = (isVertical( mDiff[xAxis], mDiff[yAxis]) ? VECT[xAxis]:VECT[yAxis]);
212
      float offset= (mTouch[mRotationVect]+cubeHalfSize)/(2*cubeHalfSize);
213

    
214
      mTouch[0] = mPoint[0];
215
      mTouch[1] = mPoint[1];
216
      mTouch[2] = mPoint[2];
217

    
218
      return new Static2D(mRotationVect,offset);
219
      }
220

    
221
///////////////////////////////////////////////////////////////////////////////////////////////////
222

    
223
    public float continueRotation(Static4D rotatedTouchPoint)
224
      {
225
      mDiff[0] = rotatedTouchPoint.get0()-mTouch[0];
226
      mDiff[1] = rotatedTouchPoint.get1()-mTouch[1];
227
      mDiff[2] = rotatedTouchPoint.get2()-mTouch[2];
228

    
229
      int xAxis= retFaceXaxis(mLastTouchedFace);
230
      int yAxis= retFaceYaxis(mLastTouchedFace);
231
      int sign = retFaceRotationSign(mLastTouchedFace);
232
      float angle = (mRotationVect==xAxis ? mDiff[yAxis] : -mDiff[xAxis]);
233

    
234
      return sign*angle;
235
      }
236
}
(3-3/6)