Project

General

Profile

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

distorted-objectlib / src / main / java / org / distorted / objectlib / touchcontrol / TouchControlShapeChanging.java @ 3a0a23bf

1 57ef6378 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
2
// Copyright 2021 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.objectlib.touchcontrol;
21
22
import org.distorted.library.main.QuatHelper;
23 92a6fc8b Leszek Koltunski
import org.distorted.library.type.Static3D;
24 57ef6378 Leszek Koltunski
import org.distorted.library.type.Static4D;
25
import org.distorted.objectlib.helpers.ObjectShape;
26
import org.distorted.objectlib.main.TwistyObject;
27
28
///////////////////////////////////////////////////////////////////////////////////////////////////
29
30 3a1efb32 Leszek Koltunski
public class TouchControlShapeChanging extends TouchControl
31 57ef6378 Leszek Koltunski
  {
32 ede746af Leszek Koltunski
  private static final float NOT_TOUCHED = 1000000.0f;
33 0c5d8bf7 Leszek Koltunski
  static final float[] mTmp = new float[4];
34 57ef6378 Leszek Koltunski
35 0c5d8bf7 Leszek Koltunski
  static class FaceInfo
36 57ef6378 Leszek Koltunski
    {
37 0c5d8bf7 Leszek Koltunski
    private final float[] normal;      // vector normal to the surface of the face, pointing outside.
38
    private final float distance;      // distance from (0,0,0) to the surface of the face
39
    private final float[][] vertices;  // vertices of the face. Already rotated by the initQuat and
40
                                       // moved by 'position' (arithmetic average of all positions)
41
    private final float[][] rotated;   // temp array to store vertices times rotation quaternion.
42
43
    //////////////////////////////////////////////////////////
44 57ef6378 Leszek Koltunski
45 ede746af Leszek Koltunski
    FaceInfo(float[][] verts, float size)
46 57ef6378 Leszek Koltunski
      {
47 ede746af Leszek Koltunski
      int numV = verts.length;
48
49
      vertices = new float[numV][];
50
      rotated  = new float[numV][];
51 57ef6378 Leszek Koltunski
52 ede746af Leszek Koltunski
      for(int i=0; i<numV; i++)
53
        {
54
        int len = verts[i].length;
55
        vertices[i]= new float[len];
56
        rotated[i] = new float[len];
57
58
        for(int j=0; j<len; j++) vertices[i][j] = verts[i][j]/size;
59
        }
60 57ef6378 Leszek Koltunski
61
      // assuming the first three vertices are linearly independent
62
      float a1 = vertices[0][0] - vertices[1][0];
63 3a1efb32 Leszek Koltunski
      float a2 = vertices[0][1] - vertices[1][1];
64
      float a3 = vertices[0][2] - vertices[1][2];
65 57ef6378 Leszek Koltunski
      float b1 = vertices[1][0] - vertices[2][0];
66 3a1efb32 Leszek Koltunski
      float b2 = vertices[1][1] - vertices[2][1];
67
      float b3 = vertices[1][2] - vertices[2][2];
68 57ef6378 Leszek Koltunski
69
      float vx = a2*b3-a3*b2;
70
      float vy = a3*b1-a1*b3;
71
      float vz = a1*b2-a2*b1;
72
73
      float len = (float)Math.sqrt(vx*vx+vy*vy+vz*vz);
74
75
      vx/=len;
76
      vy/=len;
77
      vz/=len;
78
79 0c5d8bf7 Leszek Koltunski
      distance = vx*vertices[0][0] + vy*vertices[0][1] + vz*vertices[0][2];
80 57ef6378 Leszek Koltunski
81 0c5d8bf7 Leszek Koltunski
      normal = new float[4];
82
      normal[0] = vx;
83
      normal[1] = vy;
84
      normal[2] = vz;
85
      normal[3] = 0.0f;
86
      }
87 57ef6378 Leszek Koltunski
88 0c5d8bf7 Leszek Koltunski
    //////////////////////////////////////////////////////////
89 ede746af Leszek Koltunski
90 0c5d8bf7 Leszek Koltunski
    public float[] getNormal()
91
      {
92
      return normal;
93 57ef6378 Leszek Koltunski
      }
94
    }
95
96 0c5d8bf7 Leszek Koltunski
  private final float[] mTouch;
97
  private final Static4D mTmpAxis;
98 57ef6378 Leszek Koltunski
  private int mNumCubits;
99
  private int[] mNumFaces;
100
  private boolean mPreparationDone;
101 0c5d8bf7 Leszek Koltunski
102
  final float[] mCamera, mPoint;
103
  final Static3D[] mRotAxis;
104
  final TwistyObject mObject;
105
  int mTouchedCubit, mTouchedFace, mNumAxis;
106
  FaceInfo[][] mInfos;
107
  float[][] mQuats;
108 57ef6378 Leszek Koltunski
109
///////////////////////////////////////////////////////////////////////////////////////////////////
110
111 3a1efb32 Leszek Koltunski
  public TouchControlShapeChanging(TwistyObject object)
112 57ef6378 Leszek Koltunski
    {
113 11fa413d Leszek Koltunski
    super(object.getObjectRatio());
114
115 57ef6378 Leszek Koltunski
    mPoint = new float[3];
116
    mCamera= new float[3];
117
    mTouch = new float[3];
118
    mObject= object;
119
    mPreparationDone = false;
120 92a6fc8b Leszek Koltunski
    mRotAxis = object.getRotationAxis();
121
    mNumAxis = mRotAxis.length;
122
    mTmpAxis = new Static4D(0,0,0,0);
123 57ef6378 Leszek Koltunski
    }
124
125
///////////////////////////////////////////////////////////////////////////////////////////////////
126
127 ede746af Leszek Koltunski
  private FaceInfo[] computeInfos(float[][] vertices, int[][] indices, float[] position, Static4D quat, float size)
128 57ef6378 Leszek Koltunski
    {
129
    int numFaces = indices.length;
130
131
    int len = position.length/3;
132
    float avgX = 0.0f;
133
    float avgY = 0.0f;
134
    float avgZ = 0.0f;
135
136
    for(int i=0; i<len; i++)
137
      {
138
      avgX += position[3*i  ];
139
      avgY += position[3*i+1];
140
      avgZ += position[3*i+2];
141
      }
142
143
    avgX /= len;
144
    avgY /= len;
145
    avgZ /= len;
146
147
    FaceInfo[] infos = new FaceInfo[numFaces];
148
    Static4D tmp;
149
150
    for(int i=0; i<numFaces; i++)
151
      {
152
      int numVerts = indices[i].length;
153 3a1efb32 Leszek Koltunski
      float[][] verts = new float[numVerts][4];
154 57ef6378 Leszek Koltunski
155 3a1efb32 Leszek Koltunski
      for(int j=0; j<numVerts; j++)
156 57ef6378 Leszek Koltunski
        {
157
        int index = indices[i][j];
158
        float x = vertices[index][0];
159
        float y = vertices[index][1];
160
        float z = vertices[index][2];
161
        float w = 1.0f;
162
163
        tmp = QuatHelper.rotateVectorByQuat(x,y,z,w,quat);
164
165
        verts[j][0] = tmp.get0() + avgX;
166
        verts[j][1] = tmp.get1() + avgY;
167
        verts[j][2] = tmp.get2() + avgZ;
168 3a1efb32 Leszek Koltunski
        verts[j][3] = 1.0f;
169 57ef6378 Leszek Koltunski
        }
170
171 ede746af Leszek Koltunski
      infos[i] = new FaceInfo(verts,size);
172 57ef6378 Leszek Koltunski
      }
173
174
    return infos;
175
    }
176
177
///////////////////////////////////////////////////////////////////////////////////////////////////
178
179
  private void prepare()
180
    {
181
    int[] numLayers = mObject.getNumLayers();
182
    float[][] positions = mObject.getCubitPositions(numLayers);
183 ede746af Leszek Koltunski
    float size = mObject.getSize();
184 57ef6378 Leszek Koltunski
    mNumCubits = positions.length;
185
    mNumFaces  = new int[mNumCubits];
186
187
    mInfos = new FaceInfo[mNumCubits][];
188
189
    for(int i=0; i<mNumCubits; i++)
190
      {
191
      int variant = mObject.getCubitVariant(i,numLayers);
192
      ObjectShape shape = mObject.getObjectShape(variant);
193 d0e6cf7f Leszek Koltunski
      Static4D quat = mObject.getCubitQuats(i,numLayers);
194 57ef6378 Leszek Koltunski
      float[][] vertices = shape.getVertices();
195
      int[][] indices = shape.getVertIndices();
196 ede746af Leszek Koltunski
      mInfos[i] = computeInfos(vertices,indices,positions[i],quat,size);
197 57ef6378 Leszek Koltunski
      mNumFaces[i] = indices.length;
198
      }
199
200
    Static4D[] quats = mObject.getQuats();
201
    int numQuats = quats.length;
202
203
    mQuats = new float[numQuats][4];
204
205
    for(int i=0; i<numQuats; i++)
206
      {
207
      Static4D q = quats[i];
208
      mQuats[i][0] = q.get0();
209
      mQuats[i][1] = q.get1();
210
      mQuats[i][2] = q.get2();
211
      mQuats[i][3] = q.get3();
212
      }
213
214
    mPreparationDone = true;
215
    }
216
217
///////////////////////////////////////////////////////////////////////////////////////////////////
218 a5bbbfb2 Leszek Koltunski
// points A, B, C are co-linear. Return true iff B is between A and C on this line.
219
// Compute D1 = A-B, D2=C-B. Then D1 and D2 are parallel vectors.
220
// They disagree in direction iff |D1+D2|<|D1-D2|
221 57ef6378 Leszek Koltunski
222 a5bbbfb2 Leszek Koltunski
  private boolean isBetween(float ax, float ay, float az,
223
                            float bx, float by, float bz,
224
                            float cx, float cy, float cz)
225 57ef6378 Leszek Koltunski
    {
226 a5bbbfb2 Leszek Koltunski
    float d1x = ax-bx;
227
    float d1y = ay-by;
228
    float d1z = az-bz;
229
230
    float d2x = cx-bx;
231
    float d2y = cy-by;
232
    float d2z = cz-bz;
233
234
    float sx = d1x+d2x;
235
    float sy = d1y+d2y;
236
    float sz = d1z+d2z;
237
238
    float dx = d1x-d2x;
239
    float dy = d1y-d2y;
240
    float dz = d1z-d2z;
241 57ef6378 Leszek Koltunski
242
    return sx*sx+sy*sy+sz*sz < dx*dx+dy*dy+dz*dz;
243
    }
244
245
///////////////////////////////////////////////////////////////////////////////////////////////////
246 a5bbbfb2 Leszek Koltunski
// General algorithm: shoot a half-line from the 'point' and count how many
247
// sides of the polygon it intersects with. The point is inside iff this number
248
// is odd. Note that this works also in case of concave polygons.
249
//
250
// Arbitrarily take point P on the plane ( we have decided on P=(vert[0]+vert[1])/2 )
251
// as the other point defining the half-line.
252
// 'point' and 'P' define a line L1 in 3D. Then for each side the pair of its vertices
253
// defines a line L2. If L1||L2 return false. Otherwise, the lines are skew so it's
254
// possible to compute points C1 and C2 on lines L1 and L2 which are closest to the
255
// other line and check if
256
//
257
// a) C1 and P are on the same side of 'point'
258
//    (which happens iff 'point' is not in between of C1 and P)
259
// b) C2 is between the two vertices.
260
//
261
// Both a) and b) together mean that the half-line intersects with side defined by (p2,d2)
262
//
263
// C1 and C2 can be computed in the following way:
264
// Let n = d1 x d2 - then vector n is perpendicular to both d1 and d2 --> (c1-c2) is
265
// parallel to n.
266
// There exist real numbers A,B,C such that
267
// c1 = p1 + A*d1
268
// c2 = p2 + B*d2 and
269
// c2 = c1 + C*n so that
270
// p1 + A*d1 + C*n = p2 + B*d2  --> (p1-p2) + A*d1 = B*d2 - C*n (*)
271
// Let n2 = n x d2. Let's multiply both sides of (*) by n2. Then
272
// (p1-p2)*n2 + A*(d1*n2) = 0 (0 because d1*n2 = n*n2 = 0)
273
// and from that A = [(p1-p2)*n2]/[d1*n2]
274
// Similarly     B = [(p2-p1)*n1]/[d2*n1]  where n1 = n x d1.
275 57ef6378 Leszek Koltunski
276 11fa413d Leszek Koltunski
  private boolean isInside(float[] point, float[][] vertices)
277 57ef6378 Leszek Koltunski
    {
278 a5bbbfb2 Leszek Koltunski
    float e1x = (vertices[0][0]+vertices[1][0])/2;
279
    float e1y = (vertices[0][1]+vertices[1][1])/2;
280
    float e1z = (vertices[0][2]+vertices[1][2])/2;
281
282
    float d1x = e1x - point[0];
283
    float d1y = e1y - point[1];
284
    float d1z = e1z - point[2];
285
286
    float ax = vertices[0][0] - vertices[1][0];
287
    float ay = vertices[0][1] - vertices[1][1];
288
    float az = vertices[0][2] - vertices[1][2];
289
290
    float normX = d1y*az - d1z*ay;
291
    float normY = d1z*ax - d1x*az;
292
    float normZ = d1x*ay - d1y*ax;
293
294
    float n1x = d1y*normZ - d1z*normY;
295
    float n1y = d1z*normX - d1x*normZ;
296
    float n1z = d1x*normY - d1y*normX;
297
298
    float p1x = point[0];
299
    float p1y = point[1];
300
    float p1z = point[2];
301
302
    int len = vertices.length;
303
    int numCrossings = 0;
304 57ef6378 Leszek Koltunski
305 a5bbbfb2 Leszek Koltunski
    for(int side=0; side<len; side++)
306 57ef6378 Leszek Koltunski
      {
307 a5bbbfb2 Leszek Koltunski
      float p2x = vertices[side][0];
308
      float p2y = vertices[side][1];
309
      float p2z = vertices[side][2];
310
311
      int next = side==len-1 ? 0 : side+1;
312
313
      float e2x = vertices[next][0];
314
      float e2y = vertices[next][1];
315
      float e2z = vertices[next][2];
316
317
      float d2x = e2x-p2x;
318
      float d2y = e2y-p2y;
319
      float d2z = e2z-p2z;
320
321
      float nx = d2y*d1z - d2z*d1y;
322
      float ny = d2z*d1x - d2x*d1z;
323
      float nz = d2x*d1y - d2y*d1x;
324
325
      float n2x = d2y*nz - d2z*ny;
326
      float n2y = d2z*nx - d2x*nz;
327
      float n2z = d2x*ny - d2y*nx;
328
329
      float dpx = p1x-p2x;
330
      float dpy = p1y-p2y;
331
      float dpz = p1z-p2z;
332
333
      float A1 =-dpx*n2x-dpy*n2y-dpz*n2z;
334
      float B1 = d1x*n2x+d1y*n2y+d1z*n2z;
335
336
      float A2 = dpx*n1x+dpy*n1y+dpz*n1z;
337
      float B2 = d2x*n1x+d2y*n1y+d2z*n1z;
338
339
      if( B1==0 || B2==0 ) continue;
340
341
      float C1 = A1/B1;
342
      float C2 = A2/B2;
343
344
      float c1x = p1x + C1*d1x;
345
      float c1y = p1y + C1*d1y;
346
      float c1z = p1z + C1*d1z;
347
348
      float c2x = p2x + C2*d2x;
349
      float c2y = p2y + C2*d2y;
350
      float c2z = p2z + C2*d2z;
351
352
      if( !isBetween(c1x,c1y,c1z, p1x,p1y,p1z, e1x,e1y,e1z ) &&
353
           isBetween(p2x,p2y,p2z, c2x,c2y,c2z, e2x,e2y,e2z )  )
354
        {
355
        numCrossings++;
356
        }
357 57ef6378 Leszek Koltunski
      }
358
359 a5bbbfb2 Leszek Koltunski
    return (numCrossings%2)==1;
360 57ef6378 Leszek Koltunski
    }
361
362
///////////////////////////////////////////////////////////////////////////////////////////////////
363
364
  private void rotateVertices(float[][] points, float[][] rotated, float[] quat)
365
    {
366
    int numPoints = points.length;
367
368
    for(int i=0; i<numPoints; i++)
369
      {
370
      QuatHelper.rotateVectorByQuat(rotated[i],points[i],quat);
371
      }
372
    }
373
374
///////////////////////////////////////////////////////////////////////////////////////////////////
375
// given precomputed mCamera and mPoint, respectively camera and touch point positions in ScreenSpace,
376
// a normalVec (nx,ny,nz) and distance (which together define a plane) compute point 'output[]' which:
377
// 1) lies on this plane
378
// 2) is co-linear with mCamera and mPoint
379
//
380
// output = camera + alpha*(point-camera), where alpha = [dist-normalVec*camera] / [normalVec*(point-camera)]
381
382 0c5d8bf7 Leszek Koltunski
  void castTouchPointOntoFace(float nx, float ny, float nz, float distance, float[] output)
383 57ef6378 Leszek Koltunski
    {
384
    float d0 = mPoint[0]-mCamera[0];
385
    float d1 = mPoint[1]-mCamera[1];
386
    float d2 = mPoint[2]-mCamera[2];
387
388
    float denom = nx*d0 + ny*d1 + nz*d2;
389
390
    if( denom != 0.0f )
391
      {
392
      float axisCam = nx*mCamera[0] + ny*mCamera[1] + nz*mCamera[2];
393
      float alpha = (distance-axisCam)/denom;
394
395
      output[0] = mCamera[0] + d0*alpha;
396
      output[1] = mCamera[1] + d1*alpha;
397
      output[2] = mCamera[2] + d2*alpha;
398
      }
399
    }
400
401
///////////////////////////////////////////////////////////////////////////////////////////////////
402
403 0c5d8bf7 Leszek Koltunski
  private boolean cubitFaceIsVisible(float nx, float ny, float nz, float distance)
404 57ef6378 Leszek Koltunski
    {
405
    return mCamera[0]*nx + mCamera[1]*ny + mCamera[2]*nz > distance;
406
    }
407
408
///////////////////////////////////////////////////////////////////////////////////////////////////
409
// FaceInfo defines a 3D plane (by means of a unit normal vector 'vector' and distance from the origin
410
// 'distance') and a list of points on the plane ('vertices').
411
//
412
// 0) rotate the face normal vector by quat
413
// 1) see if the face is visible. If not, return NOT_TOUCHED
414
// 2) else, cast the line passing through mPoint and mCamera onto this plane
415
// 3) if Z of this point is further from us than the already computed closestSoFar, return NOT_TOUCHED
416
// 4) else, rotate 'vertices' by quat and see if the casted point lies inside the polygon defined by them
417 0c5d8bf7 Leszek Koltunski
// 5) if yes, return the distance form this point to the camera; otherwise, return NOT_TOUCHED
418 57ef6378 Leszek Koltunski
419 11fa413d Leszek Koltunski
  private float cubitFaceTouched(FaceInfo info, float[] quat, float closestSoFar)
420 57ef6378 Leszek Koltunski
    {
421 0c5d8bf7 Leszek Koltunski
    QuatHelper.rotateVectorByQuat(mTmp,info.normal,quat);
422 57ef6378 Leszek Koltunski
    float nx = mTmp[0];
423
    float ny = mTmp[1];
424
    float nz = mTmp[2];
425
426 0c5d8bf7 Leszek Koltunski
    if( cubitFaceIsVisible(nx,ny,nz,info.distance) )
427 57ef6378 Leszek Koltunski
      {
428
      castTouchPointOntoFace(nx,ny,nz,info.distance,mTouch);
429
430 ede746af Leszek Koltunski
      float dx = mTouch[0]-mCamera[0];
431
      float dy = mTouch[1]-mCamera[1];
432
      float dz = mTouch[2]-mCamera[2];
433
      float dist = dx*dx + dy*dy + dz*dz;
434
435
      if( dist<closestSoFar )
436 57ef6378 Leszek Koltunski
        {
437
        rotateVertices(info.vertices,info.rotated,quat);
438 ede746af Leszek Koltunski
        if( isInside(mTouch,info.rotated) ) return dist;
439 57ef6378 Leszek Koltunski
        }
440
      }
441
442
    return NOT_TOUCHED;
443
    }
444
445 92a6fc8b Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
446
447 0c5d8bf7 Leszek Koltunski
  int computeRow(int cubit, int rotIndex)
448 92a6fc8b Leszek Koltunski
    {
449
    int row = mObject.getCubitRotRow(cubit,rotIndex);
450
451
    for(int index=0; index<32; index++)
452
      {
453
      if( (row&1)==1 ) return index;
454
      row>>=1;
455
      }
456
457
    return 0;
458
    }
459
460 57ef6378 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
461
// PUBLIC API
462
///////////////////////////////////////////////////////////////////////////////////////////////////
463
464
  public boolean objectTouched(Static4D rotatedTouchPoint, Static4D rotatedCamera)
465
    {
466
    if( !mPreparationDone ) prepare();
467
468
    mPoint[0]  = rotatedTouchPoint.get0()/mObjectRatio;
469
    mPoint[1]  = rotatedTouchPoint.get1()/mObjectRatio;
470
    mPoint[2]  = rotatedTouchPoint.get2()/mObjectRatio;
471
472
    mCamera[0] = rotatedCamera.get0()/mObjectRatio;
473
    mCamera[1] = rotatedCamera.get1()/mObjectRatio;
474
    mCamera[2] = rotatedCamera.get2()/mObjectRatio;
475
476
    float closestSoFar = NOT_TOUCHED;
477
    mTouchedCubit = -1;
478 3a1efb32 Leszek Koltunski
    mTouchedFace  = -1;
479 3a0a23bf Leszek Koltunski
    int numQuats = mQuats.length;
480 57ef6378 Leszek Koltunski
481 ede746af Leszek Koltunski
    for(int cubit=0; cubit<mNumCubits; cubit++)
482 57ef6378 Leszek Koltunski
      {
483 ede746af Leszek Koltunski
      int quatIndex = mObject.getCubitQuatIndex(cubit);
484 57ef6378 Leszek Koltunski
485 3a0a23bf Leszek Koltunski
      if( quatIndex<numQuats )
486 57ef6378 Leszek Koltunski
        {
487 3a0a23bf Leszek Koltunski
        float[] quat = mQuats[quatIndex];
488 ede746af Leszek Koltunski
489 3a0a23bf Leszek Koltunski
        for(int face=0; face<mNumFaces[cubit]; face++)
490 57ef6378 Leszek Koltunski
          {
491 3a0a23bf Leszek Koltunski
          float dist = cubitFaceTouched(mInfos[cubit][face],quat,closestSoFar);
492
493
          if( dist!=NOT_TOUCHED )
494
            {
495
            mTouchedCubit= cubit;
496
            mTouchedFace = face;
497
            closestSoFar = dist;
498
            }
499 57ef6378 Leszek Koltunski
          }
500
        }
501
      }
502 11fa413d Leszek Koltunski
/*
503 3a1efb32 Leszek Koltunski
    if( closestSoFar!=NOT_TOUCHED )
504
      {
505 ede746af Leszek Koltunski
      android.util.Log.e("D", "cubit="+mTouchedCubit+" face="+mTouchedFace+" result: "+closestSoFar);
506 3a1efb32 Leszek Koltunski
      }
507 11fa413d Leszek Koltunski
*/
508 57ef6378 Leszek Koltunski
    return closestSoFar!=NOT_TOUCHED;
509
    }
510
511
///////////////////////////////////////////////////////////////////////////////////////////////////
512 0c5d8bf7 Leszek Koltunski
// really implemented in derived classes; here present only because we need to be able to
513
// instantiate an object of this class for MODE_REPLACE.
514 57ef6378 Leszek Koltunski
515 cd2e8d4c Leszek Koltunski
  public void newRotation(int[] output, Static4D rotatedTouchPoint, Static4D quat)
516 57ef6378 Leszek Koltunski
    {
517
518
    }
519
520
///////////////////////////////////////////////////////////////////////////////////////////////////
521
522
  public void getCastedRotAxis(float[] output, Static4D quat, int rotIndex)
523
    {
524 92a6fc8b Leszek Koltunski
    Static3D rotAxis = mRotAxis[rotIndex];
525
    float rx = rotAxis.get0();
526
    float ry = rotAxis.get1();
527
    float rz = rotAxis.get2();
528
529
    mTmpAxis.set(rx,ry,rz,0);
530
    Static4D result = QuatHelper.rotateVectorByQuat(mTmpAxis, quat);
531
532
    float cx =result.get0();
533
    float cy =result.get1();
534
535
    float len = (float)Math.sqrt(cx*cx+cy*cy);
536
537
    if( len!=0 )
538
      {
539
      output[0] = cx/len;
540
      output[1] = cy/len;
541
      }
542
    else
543
      {
544
      output[0] = 1;
545
      output[1] = 0;
546
      }
547 57ef6378 Leszek Koltunski
    }
548
549
///////////////////////////////////////////////////////////////////////////////////////////////////
550
551 11fa413d Leszek Koltunski
  public int getTouchedCubitFace()
552 57ef6378 Leszek Koltunski
    {
553 11fa413d Leszek Koltunski
    return mTouchedFace;
554 57ef6378 Leszek Koltunski
    }
555
556
///////////////////////////////////////////////////////////////////////////////////////////////////
557
558 11fa413d Leszek Koltunski
  public int getTouchedCubit()
559 57ef6378 Leszek Koltunski
    {
560 11fa413d Leszek Koltunski
    return mTouchedCubit;
561 57ef6378 Leszek Koltunski
    }
562 3a1efb32 Leszek Koltunski
563
///////////////////////////////////////////////////////////////////////////////////////////////////
564
565
  public float returnRotationFactor(int[] numLayers, int row)
566
    {
567
    return 1.0f;
568
    }
569 57ef6378 Leszek Koltunski
  }