Project

General

Profile

Download (6.27 KB) Statistics
| Branch: | Revision:

distorted-objectlib / src / main / java / org / distorted / objectlib / touchcontrol / TouchControlBall.java @ f2259427

1
///////////////////////////////////////////////////////////////////////////////////////////////////
2
// Copyright 2022 Leszek Koltunski                                                               //
3
//                                                                                               //
4
// This file is part of Magic Cube.                                                              //
5
//                                                                                               //
6
// Magic Cube is proprietary software licensed under an EULA which you should have received      //
7
// along with the code. If not, check https://distorted.org/magic/License-Magic-Cube.html        //
8
///////////////////////////////////////////////////////////////////////////////////////////////////
9

    
10
package org.distorted.objectlib.touchcontrol;
11

    
12
import org.distorted.library.main.QuatHelper;
13
import org.distorted.library.type.Static3D;
14
import org.distorted.library.type.Static4D;
15
import org.distorted.objectlib.main.TwistyObject;
16

    
17
///////////////////////////////////////////////////////////////////////////////////////////////////
18
// Ball-shaped objects: map the 2D swipes of user's fingers to 3D rotations
19

    
20
public class TouchControlBall extends TouchControl
21
{
22
  private final Static3D[] mRotAxis;
23
  private final float[] mPoint, mCamera;
24
  private float mLongitude, mLatitude;
25
  private final int[] mEnabledRotAxis;
26
  private final int[][][] mEnabled;
27

    
28
///////////////////////////////////////////////////////////////////////////////////////////////////
29

    
30
  public TouchControlBall(TwistyObject object)
31
    {
32
    super(object.getObjectRatio());
33

    
34
    mRotAxis = object.getRotationAxis();
35
    mEnabled = object.getEnabled();
36

    
37
    mPoint = new float[3];
38
    mCamera= new float[3];
39
    mEnabledRotAxis = new int[mRotAxis.length+1];
40
    }
41

    
42
///////////////////////////////////////////////////////////////////////////////////////////////////
43
// Longitude spans from 0 (at Guinea Bay) increasing to the east all the way to 2PI
44
// Latitude - from -PI/2 (South Pole) to +PI/2 (North Pole)
45

    
46
  private void computeLongitudeAndLatitude(float A, float B, float C)
47
    {
48
    float sqrt = (float)Math.sqrt(B*B - 4*A*C);
49
    float alpha= (-B+sqrt)/(2*A); // this is the closer point
50

    
51
    float cx = mCamera[0];
52
    float cy = mCamera[1];
53
    float cz = mCamera[2];
54

    
55
    float vx = mCamera[0]-mPoint[0];
56
    float vy = mCamera[1]-mPoint[1];
57
    float vz = mCamera[2]-mPoint[2];
58

    
59
    float px = cx + alpha*vx;
60
    float py = cy + alpha*vy;
61
    float pz = cz + alpha*vz;
62

    
63
    mLongitude = pz==0 ? 0 : (float)Math.atan(px/pz);
64
    mLatitude  = (float)Math.asin(2*py);
65

    
66
    if( pz<0 ) mLongitude += Math.PI;
67
    else if( px<0 ) mLongitude += 2*Math.PI;
68
    }
69

    
70
///////////////////////////////////////////////////////////////////////////////////////////////////
71
// this is Masterball-specific. See TwistyMasterball.getEnabled()
72

    
73
  private int returnTouchedFace()
74
    {
75
    float t = (float)(mLongitude + Math.PI/8);
76
    if( t>2*Math.PI ) t-=(2*Math.PI);
77
    int ret = (int)(t/(Math.PI/4));
78
    return ret<8 ? ret : 7;
79
    }
80

    
81
///////////////////////////////////////////////////////////////////////////////////////////////////
82
// this is Masterball-specific. No parts in any faces.
83

    
84
  private int returnTouchedPart()
85
    {
86
    return 0;
87
    }
88

    
89
///////////////////////////////////////////////////////////////////////////////////////////////////
90

    
91
  private void computeEnabledAxis()
92
    {
93
    int face = returnTouchedFace();
94
    int part = returnTouchedPart();
95
    int num = mEnabled[face][0].length;
96
    mEnabledRotAxis[0] = num;
97
    System.arraycopy(mEnabled[face][part], 0, mEnabledRotAxis, 1, num);
98
    }
99

    
100
///////////////////////////////////////////////////////////////////////////////////////////////////
101

    
102
  public float returnRotationFactor(int[] numLayers, int row)
103
    {
104
    return 1.0f;
105
    }
106

    
107
///////////////////////////////////////////////////////////////////////////////////////////////////
108

    
109
  public int getTouchedCubitFace()
110
    {
111
    return 0;
112
    }
113

    
114
///////////////////////////////////////////////////////////////////////////////////////////////////
115

    
116
  public int getTouchedCubit()
117
    {
118
    return 0;
119
    }
120

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

    
123
  public boolean objectTouched(Static4D rotatedTouchPoint, Static4D rotatedCamera)
124
    {
125
    mPoint[0]  = rotatedTouchPoint.get0()/mObjectRatio;
126
    mPoint[1]  = rotatedTouchPoint.get1()/mObjectRatio;
127
    mPoint[2]  = rotatedTouchPoint.get2()/mObjectRatio;
128

    
129
    mCamera[0] = rotatedCamera.get0()/mObjectRatio;
130
    mCamera[1] = rotatedCamera.get1()/mObjectRatio;
131
    mCamera[2] = rotatedCamera.get2()/mObjectRatio;
132

    
133
    float vx = mCamera[0]-mPoint[0];
134
    float vy = mCamera[1]-mPoint[1];
135
    float vz = mCamera[2]-mPoint[2];
136

    
137
    float R = 0.5f;
138
    float A = vx*vx + vy*vy + vz*vz;
139
    float B = 2*(vx*mCamera[0] + vy*mCamera[1] + vz*mCamera[2]);
140
    float C = (mCamera[0]*mCamera[0] + mCamera[1]*mCamera[1] + mCamera[2]*mCamera[2]) - R*R;
141

    
142
    if( B*B >= 4*A*C )
143
      {
144
      computeLongitudeAndLatitude(A,B,C);
145
      return true;
146
      }
147

    
148
    return false;
149
    }
150

    
151
///////////////////////////////////////////////////////////////////////////////////////////////////
152
// TODO
153

    
154
  public void newRotation(int[] output, Static4D rotatedTouchPoint, Static4D quat)
155
    {
156
    computeEnabledAxis();
157
/*
158
    int rotIndex = computeRotationIndex( mCastedRotAxis[mLastTouchedFace], mMove2D, mEnabledRotAxis);
159
    float offset = computeOffset(mPoint2D, mCastedRotAxis[mLastTouchedFace][rotIndex]);
160
    int row      = computeRowFromOffset(mLastTouchedFace,rotIndex,offset);
161
*/
162
    int rotIndex = 0;
163
    int row = 0;
164

    
165
    output[0] = rotIndex;
166
    output[1] = row;
167
    }
168

    
169
///////////////////////////////////////////////////////////////////////////////////////////////////
170
// simply cast the appropriate rotational axis of the object to the screen surface.
171

    
172
  public void getCastedRotAxis(float[] output, Static4D quat, int axisIndex)
173
    {
174
    Static3D a = mRotAxis[axisIndex];
175
    Static4D result = QuatHelper.rotateVectorByQuat(a.get0(),a.get1(),a.get2(),0,quat);
176

    
177
    float cx = result.get0();
178
    float cy = result.get1();
179
    float len= (float)Math.sqrt(cx*cx+cy*cy);
180

    
181
    if( len!=0 )
182
      {
183
      output[0] = cx/len;
184
      output[1] = cy/len;
185
      }
186
    else
187
      {
188
      output[0] = 1;
189
      output[1] = 0;
190
      }
191
    }
192
}
(2-2/13)