Project

General

Profile

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

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

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.Static3D;
24
import org.distorted.library.type.Static4D;
25

    
26
///////////////////////////////////////////////////////////////////////////////////////////////////
27

    
28
public abstract class RubikObjectMovement
29
  {
30
  float[] mTouch;
31
  int mRotationVect, mLastTouchedAxis;
32

    
33
  private float[] mPoint, mCamera, mDiff;
34
  private int mLastTouchedLR;
35
  private int mNumAxis, mNumFacesPerAxis;
36
  private int[] mPossible;
37
  private float mDistanceCenterFace;
38
  private Static3D[] mAxis;
39

    
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
  abstract void fillPossibleRotations(int axis, int[] output);
46

    
47
///////////////////////////////////////////////////////////////////////////////////////////////////
48

    
49
  RubikObjectMovement(Static3D[] axis, int numFacesPerAxis, float distance)
50
    {
51
    mPoint = new float[3];
52
    mCamera= new float[3];
53
    mDiff  = new float[3];
54
    mTouch = new float[3];
55

    
56
    mAxis = axis;
57
    mNumAxis = mAxis.length;
58
    mNumFacesPerAxis = numFacesPerAxis;
59
    mDistanceCenterFace = distance;
60
    mPossible = new int[mNumAxis-1];
61
    }
62

    
63
///////////////////////////////////////////////////////////////////////////////////////////////////
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
///////////////////////////////////////////////////////////////////////////////////////////////////
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
        if( faceIsVisible(mAxis[mLastTouchedAxis], mLastTouchedLR) )
123
          {
124
          castTouchPointOntoFace(mAxis[mLastTouchedAxis], mLastTouchedLR, mTouch);
125

    
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
    castTouchPointOntoFace(mAxis[mLastTouchedAxis], mLastTouchedLR, mDiff);
147

    
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
  }
(6-6/8)