Project

General

Profile

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

distorted-objectlib / src / main / java / org / distorted / objectlib / touchcontrol / TouchControlShapeChanging.java @ 644c217a

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