Project

General

Profile

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

magiccube / src / main / java / org / distorted / object / RubikCubeMovement.java @ 3c4a326c

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.Static4D;
23

    
24
///////////////////////////////////////////////////////////////////////////////////////////////////
25

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

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

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

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

    
45
///////////////////////////////////////////////////////////////////////////////////////////////////
46

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

    
52
///////////////////////////////////////////////////////////////////////////////////////////////////
53

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

    
59
///////////////////////////////////////////////////////////////////////////////////////////////////
60

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

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

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

    
83
      return -1;
84
      }
85

    
86
///////////////////////////////////////////////////////////////////////////////////////////////////
87

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

    
100
      return -1;
101
      }
102

    
103
///////////////////////////////////////////////////////////////////////////////////////////////////
104

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

    
117
      return -1;
118
      }
119

    
120
///////////////////////////////////////////////////////////////////////////////////////////////////
121

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

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

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

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

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

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

    
148
///////////////////////////////////////////////////////////////////////////////////////////////////
149

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

    
158
///////////////////////////////////////////////////////////////////////////////////////////////////
159
// PUBLIC API
160
///////////////////////////////////////////////////////////////////////////////////////////////////
161

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

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

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

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

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

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

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

    
192
///////////////////////////////////////////////////////////////////////////////////////////////////
193

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

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

    
202
      castTouchPointOntoFace(mLastTouchedFace,cubeHalfSize,mDiff);
203

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

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

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

    
217
      Static4D result=null;
218

    
219
      switch(mRotationVect)
220
        {
221
        case VECTX: result = new Static4D(1,0,0,offset); break;
222
        case VECTY: result = new Static4D(0,1,0,offset); break;
223
        case VECTZ: result = new Static4D(0,0,1,offset); break;
224
        }
225

    
226
      return result;
227
      }
228

    
229
///////////////////////////////////////////////////////////////////////////////////////////////////
230

    
231
    public float continueRotation(Static4D rotatedTouchPoint)
232
      {
233
      mDiff[0] = rotatedTouchPoint.get0()-mTouch[0];
234
      mDiff[1] = rotatedTouchPoint.get1()-mTouch[1];
235
      mDiff[2] = rotatedTouchPoint.get2()-mTouch[2];
236

    
237
      int xAxis= retFaceXaxis(mLastTouchedFace);
238
      int yAxis= retFaceYaxis(mLastTouchedFace);
239
      int sign = retFaceRotationSign(mLastTouchedFace);
240
      float angle = (mRotationVect==xAxis ? mDiff[yAxis] : -mDiff[xAxis]);
241

    
242
      return sign*angle;
243
      }
244
}
(3-3/6)