Project

General

Profile

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

magiccube / src / main / java / org / distorted / object / RubikObjectMovement.java @ 37a25788

1 27a70eae Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
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 efef689c Leszek Koltunski
import org.distorted.library.type.Static2D;
23 37a25788 Leszek Koltunski
import org.distorted.library.type.Static3D;
24 27a70eae Leszek Koltunski
import org.distorted.library.type.Static4D;
25
26
///////////////////////////////////////////////////////////////////////////////////////////////////
27
28
public abstract class RubikObjectMovement
29
  {
30 37a25788 Leszek Koltunski
  float[] mTouch;
31 dd65ead3 Leszek Koltunski
  int mRotationVect, mLastTouchedAxis;
32
33 37a25788 Leszek Koltunski
  private float[] mPoint, mCamera, mDiff;
34 dd65ead3 Leszek Koltunski
  private int mLastTouchedLR;
35
  private int mNumAxis, mNumFacesPerAxis;
36
  private int[] mPossible;
37 37a25788 Leszek Koltunski
  private float mDistanceCenterFace;
38
  private Static3D[] mAxis;
39 dd65ead3 Leszek Koltunski
40
///////////////////////////////////////////////////////////////////////////////////////////////////
41
42
  abstract boolean isInsideFace(float[] point);
43
  abstract float fillUpRotationVectAndOffset(float[] vect, int[] possible);
44
  abstract float returnAngle(float[] vect, int[] possible);
45 37a25788 Leszek Koltunski
  abstract void fillPossibleRotations(int axis, int[] output);
46 dd65ead3 Leszek Koltunski
47
///////////////////////////////////////////////////////////////////////////////////////////////////
48
49 37a25788 Leszek Koltunski
  RubikObjectMovement(Static3D[] axis, int numFacesPerAxis, float distance)
50 dd65ead3 Leszek Koltunski
    {
51
    mPoint = new float[3];
52
    mCamera= new float[3];
53
    mDiff  = new float[3];
54
    mTouch = new float[3];
55
56 37a25788 Leszek Koltunski
    mAxis = axis;
57
    mNumAxis = mAxis.length;
58 dd65ead3 Leszek Koltunski
    mNumFacesPerAxis = numFacesPerAxis;
59 37a25788 Leszek Koltunski
    mDistanceCenterFace = distance;
60 dd65ead3 Leszek Koltunski
    mPossible = new int[mNumAxis-1];
61
    }
62
63 37a25788 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
64
65
  private boolean faceIsVisible(Static3D axis, int lr)
66
    {
67
    float castCameraOnAxis = mCamera[0]*axis.get0() + mCamera[1]*axis.get1() + mCamera[2]*axis.get2();
68
    return (2*lr-1)*castCameraOnAxis > mDistanceCenterFace;
69
    }
70
71
///////////////////////////////////////////////////////////////////////////////////////////////////
72
// given precomputed mCamera and mPoint, respectively camera and touch point positions in ScreenSpace,
73
// compute point 'output[]' which:
74
// 1) lies on a face of the Object, i.e. surface defined by (axis, distance from (0,0,0)) [and this
75
//    distance is +-mDistanceCenterFace, depending if it is the face on the left or the right end of
76
//    the axis] (lr=0 or 1, so (2lr-1)*mDistanceCenterFace)
77
// 2) is co-linear with mCamera and mPoint
78
//
79
// output = camera + alpha*(point-camera), where alpha = [dist-axis*camera] / [axis*(point-camera)]
80
81
  private void castTouchPointOntoFace(Static3D axis, int lr, float[] output)
82
    {
83
    float d0 = mPoint[0]-mCamera[0];
84
    float d1 = mPoint[1]-mCamera[1];
85
    float d2 = mPoint[2]-mCamera[2];
86
    float a0 = axis.get0();
87
    float a1 = axis.get1();
88
    float a2 = axis.get2();
89
90
    float denom = a0*d0 + a1*d1 + a2*d2;
91
92
    if( denom != 0.0f )
93
      {
94
      float axisCam = a0*mCamera[0] + a1*mCamera[1] + a2*mCamera[2];
95
      float distance = (2*lr-1)*mDistanceCenterFace;
96
      float alpha = (distance-axisCam)/denom;
97
98
      output[0] = mCamera[0] + d0*alpha;
99
      output[1] = mCamera[1] + d1*alpha;
100
      output[2] = mCamera[2] + d2*alpha;
101
      }
102
    }
103
104 dd65ead3 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
105
// PUBLIC API
106
///////////////////////////////////////////////////////////////////////////////////////////////////
107
108
  public boolean faceTouched(Static4D rotatedTouchPoint, Static4D rotatedCamera)
109
    {
110
    mPoint[0]  = rotatedTouchPoint.get0()/RubikObject.OBJECT_SCREEN_RATIO;
111
    mPoint[1]  = rotatedTouchPoint.get1()/RubikObject.OBJECT_SCREEN_RATIO;
112
    mPoint[2]  = rotatedTouchPoint.get2()/RubikObject.OBJECT_SCREEN_RATIO;
113
114
    mCamera[0] = rotatedCamera.get0()/RubikObject.OBJECT_SCREEN_RATIO;
115
    mCamera[1] = rotatedCamera.get1()/RubikObject.OBJECT_SCREEN_RATIO;
116
    mCamera[2] = rotatedCamera.get2()/RubikObject.OBJECT_SCREEN_RATIO;
117
118
    for( mLastTouchedAxis=0; mLastTouchedAxis<mNumAxis; mLastTouchedAxis++)
119
      {
120
      for( mLastTouchedLR=0; mLastTouchedLR<mNumFacesPerAxis; mLastTouchedLR++)
121
        {
122 37a25788 Leszek Koltunski
        if( faceIsVisible(mAxis[mLastTouchedAxis], mLastTouchedLR) )
123 dd65ead3 Leszek Koltunski
          {
124 37a25788 Leszek Koltunski
          castTouchPointOntoFace(mAxis[mLastTouchedAxis], mLastTouchedLR, mTouch);
125 dd65ead3 Leszek Koltunski
126
          if( isInsideFace(mTouch) )
127
            {
128
            fillPossibleRotations(mLastTouchedAxis, mPossible);
129
            return true;
130
            }
131
          }
132
        }
133
      }
134
135
    return false;
136
    }
137
138
///////////////////////////////////////////////////////////////////////////////////////////////////
139
140
  public Static2D newRotation(Static4D rotatedTouchPoint)
141
    {
142
    mPoint[0] = rotatedTouchPoint.get0()/RubikObject.OBJECT_SCREEN_RATIO;
143
    mPoint[1] = rotatedTouchPoint.get1()/RubikObject.OBJECT_SCREEN_RATIO;
144
    mPoint[2] = rotatedTouchPoint.get2()/RubikObject.OBJECT_SCREEN_RATIO;
145
146 37a25788 Leszek Koltunski
    castTouchPointOntoFace(mAxis[mLastTouchedAxis], mLastTouchedLR, mDiff);
147 dd65ead3 Leszek Koltunski
148
    mDiff[0] -= mTouch[0];
149
    mDiff[1] -= mTouch[1];
150
    mDiff[2] -= mTouch[2];
151
152
    float offset = fillUpRotationVectAndOffset(mDiff, mPossible);
153
154
    mTouch[0] = mPoint[0];
155
    mTouch[1] = mPoint[1];
156
    mTouch[2] = mPoint[2];
157
158
    return new Static2D(mRotationVect,offset);
159
    }
160
161
///////////////////////////////////////////////////////////////////////////////////////////////////
162
163
  public float continueRotation(Static4D rotatedTouchPoint)
164
    {
165
    mDiff[0] = rotatedTouchPoint.get0()/RubikObject.OBJECT_SCREEN_RATIO - mTouch[0];
166
    mDiff[1] = rotatedTouchPoint.get1()/RubikObject.OBJECT_SCREEN_RATIO - mTouch[1];
167
    mDiff[2] = rotatedTouchPoint.get2()/RubikObject.OBJECT_SCREEN_RATIO - mTouch[2];
168
169
    return (mLastTouchedLR-0.5f)*returnAngle(mDiff, mPossible);
170
    }
171 27a70eae Leszek Koltunski
  }