Project

General

Profile

« Previous | Next » 

Revision ee35e63c

Added by Leszek Koltunski over 3 years ago

Beginnings of support for the Helicopter.

View differences:

src/main/java/org/distorted/objects/RubikCube.java
23 23
import android.graphics.Canvas;
24 24
import android.graphics.Paint;
25 25

  
26
import com.google.firebase.crashlytics.FirebaseCrashlytics;
27

  
28 26
import org.distorted.library.effect.VertexEffectDeform;
29 27
import org.distorted.library.effect.VertexEffectMove;
30 28
import org.distorted.library.effect.VertexEffectRotate;
src/main/java/org/distorted/objects/RubikDino.java
537 537
    }
538 538

  
539 539
///////////////////////////////////////////////////////////////////////////////////////////////////
540
// TODO  (only needed for solvers - there are no Dino solvers ATM)
540
// only needed for solvers - there are no Dino solvers ATM)
541 541

  
542 542
  public String retObjectString()
543 543
    {
src/main/java/org/distorted/objects/RubikHelicopter.java
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.objects;
21

  
22
import android.content.res.Resources;
23
import android.graphics.Canvas;
24
import android.graphics.Paint;
25

  
26
import org.distorted.library.effect.MatrixEffectQuaternion;
27
import org.distorted.library.effect.VertexEffectDeform;
28
import org.distorted.library.effect.VertexEffectMove;
29
import org.distorted.library.effect.VertexEffectRotate;
30
import org.distorted.library.effect.VertexEffectScale;
31
import org.distorted.library.main.DistortedEffects;
32
import org.distorted.library.main.DistortedTexture;
33
import org.distorted.library.mesh.MeshBase;
34
import org.distorted.library.mesh.MeshJoined;
35
import org.distorted.library.mesh.MeshPolygon;
36
import org.distorted.library.mesh.MeshSquare;
37
import org.distorted.library.type.Static1D;
38
import org.distorted.library.type.Static3D;
39
import org.distorted.library.type.Static4D;
40
import org.distorted.main.RubikSurfaceView;
41

  
42
import java.util.Random;
43

  
44
import static org.distorted.effects.scramble.ScrambleEffect.START_AXIS;
45

  
46
///////////////////////////////////////////////////////////////////////////////////////////////////
47

  
48
public class RubikHelicopter extends RubikObject
49
{
50
  private static final float SQ2 = (float)Math.sqrt(2);
51
  private static final float SQ3 = (float)Math.sqrt(3);
52

  
53
  private static final int FACES_PER_CUBIT =6;
54

  
55
  // the six rotation axis of a Helicopter. Must be normalized.
56
  static final Static3D[] ROT_AXIS = new Static3D[]
57
         {
58
           new Static3D(     0, +SQ2/2, -SQ2/2),
59
           new Static3D(     0, -SQ2/2, -SQ2/2),
60
           new Static3D(+SQ2/2,      0, -SQ2/2),
61
           new Static3D(-SQ2/2,      0, -SQ2/2),
62
           new Static3D(+SQ2/2, -SQ2/2,      0),
63
           new Static3D(-SQ2/2, -SQ2/2,      0)
64
         };
65

  
66
  // the six axis that determine the faces
67
  static final Static3D[] FACE_AXIS = new Static3D[]
68
         {
69
           new Static3D(1,0,0), new Static3D(-1,0,0),
70
           new Static3D(0,1,0), new Static3D(0,-1,0),
71
           new Static3D(0,0,1), new Static3D(0,0,-1)
72
         };
73

  
74
  private static final int[] FACE_COLORS = new int[]
75
         {
76
           0xffffff00, 0xffffffff,   // FACE_AXIS[0] (right-YELLOW) FACE_AXIS[1] (left  -WHITE)
77
           0xff0000ff, 0xff00ff00,   // FACE_AXIS[2] (top  -BLUE  ) FACE_AXIS[3] (bottom-GREEN)
78
           0xffff0000, 0xffb5651d    // FACE_AXIS[4] (front-RED   ) FACE_AXIS[5] (back  -BROWN)
79
         };
80

  
81
  // All legal rotation quats of a HELICOPTER (same as the Cube!)
82
  private static final Static4D[] QUATS = new Static4D[]
83
         {
84
           new Static4D( 0.00f,  0.00f,  0.00f,  1.00f ),
85
           new Static4D( 1.00f,  0.00f,  0.00f,  0.00f ),
86
           new Static4D( 0.00f,  1.00f,  0.00f,  0.00f ),
87
           new Static4D( 0.00f,  0.00f,  1.00f,  0.00f ),
88

  
89
           new Static4D( SQ2/2,  SQ2/2,  0.00f,  0.00f ),
90
           new Static4D( SQ2/2, -SQ2/2,  0.00f,  0.00f ),
91
           new Static4D( SQ2/2,  0.00f,  SQ2/2,  0.00f ),
92
           new Static4D( SQ2/2,  0.00f, -SQ2/2,  0.00f ),
93
           new Static4D( SQ2/2,  0.00f,  0.00f,  SQ2/2 ),
94
           new Static4D( SQ2/2,  0.00f,  0.00f, -SQ2/2 ),
95
           new Static4D( 0.00f,  SQ2/2,  SQ2/2,  0.00f ),
96
           new Static4D( 0.00f,  SQ2/2, -SQ2/2,  0.00f ),
97
           new Static4D( 0.00f,  SQ2/2,  0.00f,  SQ2/2 ),
98
           new Static4D( 0.00f,  SQ2/2,  0.00f, -SQ2/2 ),
99
           new Static4D( 0.00f,  0.00f,  SQ2/2,  SQ2/2 ),
100
           new Static4D( 0.00f,  0.00f,  SQ2/2, -SQ2/2 ),
101

  
102
           new Static4D( 0.50f,  0.50f,  0.50f,  0.50f ),
103
           new Static4D( 0.50f,  0.50f,  0.50f, -0.50f ),
104
           new Static4D( 0.50f,  0.50f, -0.50f,  0.50f ),
105
           new Static4D( 0.50f,  0.50f, -0.50f, -0.50f ),
106
           new Static4D( 0.50f, -0.50f,  0.50f,  0.50f ),
107
           new Static4D( 0.50f, -0.50f,  0.50f, -0.50f ),
108
           new Static4D( 0.50f, -0.50f, -0.50f,  0.50f ),
109
           new Static4D( 0.50f, -0.50f, -0.50f, -0.50f )
110
         };
111

  
112
  private static final float DIST_CORNER = 0.50f;
113
  private static final float DIST_CENTER = 0.49f;
114
  private static final float XY_CENTER   = DIST_CORNER/3;
115

  
116
  // centers of the 8 corners + 6*4 face triangles ( i.e. of the all 32 cubits)
117
  private static final Static3D[] CENTERS = new Static3D[]
118
         {
119
           new Static3D(   DIST_CORNER,   DIST_CORNER,   DIST_CORNER ),
120
           new Static3D(   DIST_CORNER,   DIST_CORNER,  -DIST_CORNER ),
121
           new Static3D(   DIST_CORNER,  -DIST_CORNER,   DIST_CORNER ),
122
           new Static3D(   DIST_CORNER,  -DIST_CORNER,  -DIST_CORNER ),
123
           new Static3D(  -DIST_CORNER,   DIST_CORNER,   DIST_CORNER ),
124
           new Static3D(  -DIST_CORNER,   DIST_CORNER,  -DIST_CORNER ),
125
           new Static3D(  -DIST_CORNER,  -DIST_CORNER,   DIST_CORNER ),
126
           new Static3D(  -DIST_CORNER,  -DIST_CORNER,  -DIST_CORNER ),
127

  
128
           new Static3D(   DIST_CENTER,     XY_CENTER,     XY_CENTER ),
129
           new Static3D(   DIST_CENTER,     XY_CENTER,    -XY_CENTER ),
130
           new Static3D(   DIST_CENTER,    -XY_CENTER,     XY_CENTER ),
131
           new Static3D(   DIST_CENTER,    -XY_CENTER,    -XY_CENTER ),
132

  
133
           new Static3D(  -DIST_CENTER,     XY_CENTER,     XY_CENTER ),
134
           new Static3D(  -DIST_CENTER,     XY_CENTER,    -XY_CENTER ),
135
           new Static3D(  -DIST_CENTER,    -XY_CENTER,     XY_CENTER ),
136
           new Static3D(  -DIST_CENTER,    -XY_CENTER,    -XY_CENTER ),
137

  
138
           new Static3D(   XY_CENTER  ,   DIST_CENTER,     XY_CENTER ),
139
           new Static3D(   XY_CENTER  ,   DIST_CENTER,    -XY_CENTER ),
140
           new Static3D(  -XY_CENTER  ,   DIST_CENTER,     XY_CENTER ),
141
           new Static3D(  -XY_CENTER  ,   DIST_CENTER,    -XY_CENTER ),
142

  
143
           new Static3D(   XY_CENTER  ,  -DIST_CENTER,     XY_CENTER ),
144
           new Static3D(   XY_CENTER  ,  -DIST_CENTER,    -XY_CENTER ),
145
           new Static3D(  -XY_CENTER  ,  -DIST_CENTER,     XY_CENTER ),
146
           new Static3D(  -XY_CENTER  ,  -DIST_CENTER,    -XY_CENTER ),
147

  
148
           new Static3D(   XY_CENTER  ,     XY_CENTER,   DIST_CENTER ),
149
           new Static3D(   XY_CENTER  ,    -XY_CENTER,   DIST_CENTER ),
150
           new Static3D(  -XY_CENTER  ,     XY_CENTER,   DIST_CENTER ),
151
           new Static3D(  -XY_CENTER  ,    -XY_CENTER,   DIST_CENTER ),
152

  
153
           new Static3D(   XY_CENTER  ,     XY_CENTER,  -DIST_CENTER ),
154
           new Static3D(   XY_CENTER  ,    -XY_CENTER,  -DIST_CENTER ),
155
           new Static3D(  -XY_CENTER  ,     XY_CENTER,  -DIST_CENTER ),
156
           new Static3D(  -XY_CENTER  ,    -XY_CENTER,  -DIST_CENTER ),
157
         };
158

  
159
  // Colors of the faces of cubits. Each cubit has 6 faces
160
  private static final int[][] mFaceMap = new int[][]
161
         {
162
           { 4,2,0, 6,6,6 },
163
           { 2,5,0, 6,6,6 },
164
           { 3,4,0, 6,6,6 },
165
           { 5,3,0, 6,6,6 },
166
           { 1,2,4, 6,6,6 },
167
           { 5,2,1, 6,6,6 },
168
           { 4,3,1, 6,6,6 },
169
           { 1,3,5, 6,6,6 },
170

  
171
           { 0 , 6,6,6,6,6 },
172
           { 0 , 6,6,6,6,6 },
173
           { 0 , 6,6,6,6,6 },
174
           { 0 , 6,6,6,6,6 },
175

  
176
           { 1 , 6,6,6,6,6 },
177
           { 1 , 6,6,6,6,6 },
178
           { 1 , 6,6,6,6,6 },
179
           { 1 , 6,6,6,6,6 },
180

  
181
           { 2 , 6,6,6,6,6 },
182
           { 2 , 6,6,6,6,6 },
183
           { 2 , 6,6,6,6,6 },
184
           { 2 , 6,6,6,6,6 },
185

  
186
           { 3 , 6,6,6,6,6 },
187
           { 3 , 6,6,6,6,6 },
188
           { 3 , 6,6,6,6,6 },
189
           { 3 , 6,6,6,6,6 },
190

  
191
           { 4 , 6,6,6,6,6 },
192
           { 4 , 6,6,6,6,6 },
193
           { 4 , 6,6,6,6,6 },
194
           { 4 , 6,6,6,6,6 },
195

  
196
           { 5 , 6,6,6,6,6 },
197
           { 5 , 6,6,6,6,6 },
198
           { 5 , 6,6,6,6,6 },
199
           { 5 , 6,6,6,6,6 },
200
         };
201

  
202
  private static MeshBase mCornerMesh, mFaceMesh;
203

  
204
///////////////////////////////////////////////////////////////////////////////////////////////////
205

  
206
  RubikHelicopter(int size, Static4D quat, DistortedTexture texture,
207
                  MeshSquare mesh, DistortedEffects effects, int[][] moves, Resources res, int scrWidth)
208
    {
209
    super(size, 60, quat, texture, mesh, effects, moves, RubikObjectList.HELI, res, scrWidth);
210
    }
211

  
212
///////////////////////////////////////////////////////////////////////////////////////////////////
213

  
214
  private void createCornerMesh()
215
    {
216
    float D = 0.02f;
217
    float E = 0.5f;
218
    float F = SQ2/4;
219

  
220
    float[] vertices0 = { -E+E/4,E/4, E/4,-E+E/4, E/4,E/4};
221

  
222
    float[] bands0 = { 1.0f    , 0,
223
                       1.0f-2*D, D*0.25f,
224
                       1.0f-4*D, D*0.35f,
225
                       1.0f-8*D, D*0.6f,
226
                       0.60f   , D*1.0f,
227
                       0.30f   , D*1.375f,
228
                       0.0f    , D*1.4f };
229

  
230
    MeshBase[] meshes = new MeshBase[6];
231

  
232
    meshes[0] = new MeshPolygon(vertices0, bands0, 3, 3);
233
    meshes[0].setEffectAssociation(0,1,0);
234
    meshes[1] = meshes[0].copy(true);
235
    meshes[1].setEffectAssociation(0,2,0);
236
    meshes[2] = meshes[0].copy(true);
237
    meshes[2].setEffectAssociation(0,4,0);
238

  
239
    float[] vertices1 = { -F,-1.0f/12, +F,-1.0f/12, 0,1.0f/6 };
240
    float[] bands1 = { 1.0f, 0.0f, 0.5f, 0.0f, 0.0f, 0.0f };
241

  
242
    meshes[3] = new MeshPolygon(vertices1,bands1,1,3);
243
    meshes[3].setEffectAssociation(0,8,0);
244
    meshes[4] = meshes[3].copy(true);
245
    meshes[4].setEffectAssociation(0,16,0);
246
    meshes[5] = meshes[3].copy(true);
247
    meshes[5].setEffectAssociation(0,32,0);
248

  
249
    mCornerMesh = new MeshJoined(meshes);
250

  
251
    Static3D axisX  = new Static3D(1,0,0);
252
    Static3D axisY  = new Static3D(0,1,0);
253
    Static3D axis0  = new Static3D(-SQ2/2,0,SQ2/2);
254
    Static3D axis1  = new Static3D(+SQ3/3,+SQ3/3,+SQ3/3);
255
    Static1D angle1 = new Static1D(+90);
256
    Static1D angle2 = new Static1D(-90);
257
    Static1D angle3 = new Static1D(-135);
258
    Static1D angle4 = new Static1D(90);
259
    Static1D angle5 = new Static1D(120);
260
    Static1D angle6 = new Static1D(240);
261
    Static3D center1= new Static3D(0,0,0);
262
    Static3D center2= new Static3D(-0.25f,-0.25f,-0.25f);
263
    Static3D move1  = new Static3D(-E/4,-E/4,0);
264
    Static3D move2  = new Static3D(-0.25f,(-1.0f/6)-0.25f,-0.25f);
265

  
266
    float d0 =-0.04f;
267
    float d1 = 0.04f;
268
    float r0 = 0.15f;
269
    float r1 = 0.10f;
270

  
271
    Static3D vec0   = new Static3D(d0*(+SQ3/3),d0*(+SQ3/3),d0*(+SQ3/3));
272
    Static3D vec1   = new Static3D(d1*(+SQ3/3),d1*(-SQ3/3),d1*(-SQ3/3));
273
    Static3D vec2   = new Static3D(d1*(-SQ3/3),d1*(+SQ3/3),d1*(-SQ3/3));
274
    Static3D vec3   = new Static3D(d1*(-SQ3/3),d1*(-SQ3/3),d1*(+SQ3/3));
275

  
276
    Static1D radius = new Static1D(0.5f);
277

  
278
    Static3D cent0  = new Static3D( 0.0f, 0.0f, 0.0f);
279
    Static3D cent1  = new Static3D(-0.5f, 0.0f, 0.0f);
280
    Static3D cent2  = new Static3D( 0.0f,-0.5f, 0.0f);
281
    Static3D cent3  = new Static3D( 0.0f, 0.0f,-0.5f);
282

  
283
    Static4D reg0   = new Static4D(0,0,0,r0);
284
    Static4D reg1   = new Static4D(0,0,0,r1);
285

  
286
    VertexEffectMove   effect0 = new VertexEffectMove(move1);
287
    VertexEffectScale  effect1 = new VertexEffectScale(new Static3D(1,1,-1));
288
    VertexEffectRotate effect2 = new VertexEffectRotate(angle1,axisX,center1);
289
    VertexEffectRotate effect3 = new VertexEffectRotate(angle2,axisY,center1);
290
    VertexEffectMove   effect4 = new VertexEffectMove(move2);
291
    VertexEffectRotate effect5 = new VertexEffectRotate(angle1,axisX,center2);
292
    VertexEffectRotate effect6 = new VertexEffectRotate(angle3,axisY,center2);
293
    VertexEffectRotate effect7 = new VertexEffectRotate(angle4,axis0,center2);
294
    VertexEffectRotate effect8 = new VertexEffectRotate(angle5,axis1,center2);
295
    VertexEffectRotate effect9 = new VertexEffectRotate(angle6,axis1,center2);
296

  
297
    VertexEffectDeform effect10= new VertexEffectDeform(vec0,radius,cent0,reg0);
298
    VertexEffectDeform effect11= new VertexEffectDeform(vec1,radius,cent1,reg1);
299
    VertexEffectDeform effect12= new VertexEffectDeform(vec2,radius,cent2,reg1);
300
    VertexEffectDeform effect13= new VertexEffectDeform(vec3,radius,cent3,reg1);
301

  
302
    effect0.setMeshAssociation( 7,-1);  // meshes 0,1,2
303
    effect1.setMeshAssociation( 6,-1);  // meshes 1,2
304
    effect2.setMeshAssociation( 2,-1);  // mesh 1
305
    effect3.setMeshAssociation( 4,-1);  // mesh 2
306
    effect4.setMeshAssociation(56,-1);  // meshes 3,4,5
307
    effect5.setMeshAssociation(56,-1);  // meshes 3,4,5
308
    effect6.setMeshAssociation(56,-1);  // meshes 3,4,5
309
    effect7.setMeshAssociation(56,-1);  // meshes 3,4,5
310
    effect8.setMeshAssociation(16,-1);  // mesh 4
311
    effect9.setMeshAssociation(32,-1);  // mesh 5
312

  
313
    effect10.setMeshAssociation(63,-1); // all meshes
314
    effect11.setMeshAssociation(63,-1); // all meshes
315
    effect12.setMeshAssociation(63,-1); // all meshes
316
    effect13.setMeshAssociation(63,-1); // all meshes
317

  
318
    mCornerMesh.apply(effect0);
319
    mCornerMesh.apply(effect1);
320
    mCornerMesh.apply(effect2);
321
    mCornerMesh.apply(effect3);
322
    mCornerMesh.apply(effect4);
323
    mCornerMesh.apply(effect5);
324
    mCornerMesh.apply(effect6);
325
    mCornerMesh.apply(effect7);
326
    mCornerMesh.apply(effect8);
327
    mCornerMesh.apply(effect9);
328

  
329
    mCornerMesh.apply(effect10);
330
    mCornerMesh.apply(effect11);
331
    mCornerMesh.apply(effect12);
332
    mCornerMesh.apply(effect13);
333

  
334
    mCornerMesh.mergeEffComponents();
335
    }
336

  
337
///////////////////////////////////////////////////////////////////////////////////////////////////
338

  
339
  private void createFaceMesh()
340
    {
341
    float D = 0.02f;
342
    float E = 0.5f;
343
    float F = SQ2/4;
344

  
345
    float[] vertices0 = { -E+E/4,E/4, E/4,-E+E/4, E/4,E/4};
346

  
347
    float[] bands0 = { 1.0f    , 0,
348
                       1.0f-2*D, D*0.25f,
349
                       1.0f-4*D, D*0.35f,
350
                       1.0f-8*D, D*0.6f,
351
                       0.60f   , D*1.0f,
352
                       0.30f   , D*1.375f,
353
                       0.0f    , D*1.4f };
354

  
355
    MeshBase[] meshes = new MeshBase[6];
356

  
357
    meshes[0] = new MeshPolygon(vertices0, bands0, 3, 3);
358
    meshes[0].setEffectAssociation(0,1,0);
359

  
360
    // TODO
361

  
362
    mFaceMesh.mergeEffComponents();
363
    }
364

  
365
///////////////////////////////////////////////////////////////////////////////////////////////////
366

  
367
  float getScreenRatio()
368
    {
369
    return 1.0f;
370
    }
371

  
372
///////////////////////////////////////////////////////////////////////////////////////////////////
373

  
374
  Static4D[] getQuats()
375
    {
376
    return QUATS;
377
    }
378

  
379
///////////////////////////////////////////////////////////////////////////////////////////////////
380

  
381
  int getNumFaces()
382
    {
383
    return FACE_COLORS.length;
384
    }
385

  
386
///////////////////////////////////////////////////////////////////////////////////////////////////
387

  
388
  int getNumStickerTypes()
389
    {
390
    return 1;
391
    }
392

  
393
///////////////////////////////////////////////////////////////////////////////////////////////////
394

  
395
  int getNumCubitFaces()
396
    {
397
    return FACES_PER_CUBIT;
398
    }
399

  
400
///////////////////////////////////////////////////////////////////////////////////////////////////
401

  
402
  Static3D[] getCubitPositions(int size)
403
    {
404
    return CENTERS;
405
    }
406

  
407
///////////////////////////////////////////////////////////////////////////////////////////////////
408
// TODO
409

  
410
  private int getQuatIndex(int cubit)
411
    {
412
    switch(cubit)
413
      {
414
      case  0:
415
      case  1:
416
      case  2:
417
      case  3:
418
      case  4:
419
      case  5:
420
      case  6:
421
      case  7:
422
      case  8:
423
      case  9:
424
      case 10:
425
      case 11:
426
      case 12:
427
      case 13:
428
      case 14:
429
      case 15:
430
      case 16:
431
      case 17:
432
      case 18:
433
      case 19:
434
      case 20:
435
      case 21:
436
      case 22:
437
      case 23:
438
      case 24:
439
      case 25:
440
      case 26:
441
      case 27:
442
      case 28:
443
      case 29:
444
      case 30:
445
      case 31:
446
      }
447

  
448
    return -1;
449
    }
450

  
451
///////////////////////////////////////////////////////////////////////////////////////////////////
452

  
453
  MeshBase createCubitMesh(int cubit)
454
    {
455
    MeshBase mesh;
456

  
457
    if( cubit<8 )
458
      {
459
      if( mCornerMesh==null ) createCornerMesh();
460
      mesh = mCornerMesh.copy(true);
461
      }
462
    else
463
      {
464
      if( mFaceMesh==null ) createFaceMesh();
465
      mesh = mFaceMesh.copy(true);
466
      }
467

  
468
    int index = getQuatIndex(cubit);
469
    MatrixEffectQuaternion quat = new MatrixEffectQuaternion( QUATS[index], new Static3D(0,0,0) );
470
    mesh.apply(quat,0xffffffff,0);
471

  
472
    return mesh;
473
    }
474

  
475
///////////////////////////////////////////////////////////////////////////////////////////////////
476

  
477
  int getFaceColor(int cubit, int cubitface, int size)
478
    {
479
    return mFaceMap[cubit][cubitface];
480
    }
481

  
482
///////////////////////////////////////////////////////////////////////////////////////////////////
483

  
484
  void createFaceTexture(Canvas canvas, Paint paint, int face, int left, int top, int side)
485
    {
486
    float STROKE = 0.035f*side;
487
    float L= left+0.125f*side;
488
    float H= 0.375f*side;
489
    float LEN = 0.5f*side;
490

  
491
    paint.setAntiAlias(true);
492
    paint.setStrokeWidth(STROKE);
493
    paint.setColor(FACE_COLORS[face]);
494
    paint.setStyle(Paint.Style.FILL);
495

  
496
    canvas.drawRect(left,top,left+side,top+side,paint);
497

  
498
    paint.setColor(INTERIOR_COLOR);
499
    paint.setStyle(Paint.Style.STROKE);
500

  
501
    canvas.drawLine( L    , H,  L+LEN, H    , paint);
502
    canvas.drawLine( L    , H,  L+LEN, H+LEN, paint);
503
    canvas.drawLine( L+LEN, H,  L+LEN, H+LEN, paint);
504

  
505
    float S1 = 0.125f*side;
506
    float S2 = 0.070f*side;
507
    float X  = 0.7f*S2;
508

  
509
    float LA = left+0.625f*side;
510
    float RA = left+0.125f*side;
511
    float TA = 0.375f*side;
512
    float BA = 0.875f*side;
513

  
514
    canvas.drawArc( LA-S1, TA     , LA     , TA+S1, 270, 90, false, paint);
515
    canvas.drawArc( RA+X , TA     , RA+X+S2, TA+S2, 135,135, false, paint);
516
    canvas.drawArc( LA-S2, BA-X-S2, LA     , BA-X ,   0,135, false, paint);
517
    }
518

  
519
///////////////////////////////////////////////////////////////////////////////////////////////////
520

  
521
  float returnMultiplier()
522
    {
523
    return 2.0f;
524
    }
525

  
526
///////////////////////////////////////////////////////////////////////////////////////////////////
527

  
528
  float[] getRowChances()
529
    {
530
    float[] chances = new float[4];
531

  
532
    chances[0] = 0.5f;
533
    chances[1] = 0.5f;
534
    chances[2] = 0.5f;
535
    chances[3] = 1.0f;
536

  
537
    return chances;
538
    }
539

  
540
///////////////////////////////////////////////////////////////////////////////////////////////////
541
// PUBLIC API
542

  
543
  public Static3D[] getRotationAxis()
544
    {
545
    return ROT_AXIS;
546
    }
547

  
548
///////////////////////////////////////////////////////////////////////////////////////////////////
549

  
550
  public int getBasicAngle()
551
    {
552
    return 2;
553
    }
554

  
555
///////////////////////////////////////////////////////////////////////////////////////////////////
556

  
557
  public int computeRowFromOffset(float offset)
558
    {
559
    return offset<0.25f ? 0:1;
560
    }
561

  
562
///////////////////////////////////////////////////////////////////////////////////////////////////
563

  
564
  public float returnRotationFactor(float offset)
565
    {
566
    return 1.0f;
567
    }
568

  
569
///////////////////////////////////////////////////////////////////////////////////////////////////
570

  
571
  public int randomizeNewRotAxis(Random rnd, int oldRotAxis)
572
    {
573
    int numAxis = ROTATION_AXIS.length;
574

  
575
    if( oldRotAxis == START_AXIS )
576
      {
577
      return rnd.nextInt(numAxis);
578
      }
579
    else
580
      {
581
      int newVector = rnd.nextInt(numAxis-2);
582

  
583
      switch(oldRotAxis)
584
        {
585
        case  0:
586
        case  1: return newVector+2;
587
        case  2:
588
        case  3: return (newVector==0 || newVector==1) ? newVector:newVector+2;
589
        default: return newVector;
590
        }
591
      }
592
    }
593

  
594
///////////////////////////////////////////////////////////////////////////////////////////////////
595

  
596
  public int randomizeNewRow(Random rnd, int oldRotAxis, int oldRow, int newRotAxis)
597
    {
598
    float rowFloat = rnd.nextFloat();
599

  
600
    for(int row=0; row<mRowChances.length; row++)
601
      {
602
      if( rowFloat<=mRowChances[row] ) return row;
603
      }
604

  
605
    return 0;
606
    }
607

  
608
///////////////////////////////////////////////////////////////////////////////////////////////////
609
// remember about the double cover or unit quaternions!
610

  
611
  private int mulQuat(int q1, int q2)
612
    {
613
    Static4D result = RubikSurfaceView.quatMultiply(QUATS[q1],QUATS[q2]);
614

  
615
    float rX = result.get0();
616
    float rY = result.get1();
617
    float rZ = result.get2();
618
    float rW = result.get3();
619

  
620
    final float MAX_ERROR = 0.1f;
621
    float dX,dY,dZ,dW;
622

  
623
    for(int i=0; i<QUATS.length; i++)
624
      {
625
      dX = QUATS[i].get0() - rX;
626
      dY = QUATS[i].get1() - rY;
627
      dZ = QUATS[i].get2() - rZ;
628
      dW = QUATS[i].get3() - rW;
629

  
630
      if( dX<MAX_ERROR && dX>-MAX_ERROR &&
631
          dY<MAX_ERROR && dY>-MAX_ERROR &&
632
          dZ<MAX_ERROR && dZ>-MAX_ERROR &&
633
          dW<MAX_ERROR && dW>-MAX_ERROR  ) return i;
634

  
635
      dX = QUATS[i].get0() + rX;
636
      dY = QUATS[i].get1() + rY;
637
      dZ = QUATS[i].get2() + rZ;
638
      dW = QUATS[i].get3() + rW;
639

  
640
      if( dX<MAX_ERROR && dX>-MAX_ERROR &&
641
          dY<MAX_ERROR && dY>-MAX_ERROR &&
642
          dZ<MAX_ERROR && dZ>-MAX_ERROR &&
643
          dW<MAX_ERROR && dW>-MAX_ERROR  ) return i;
644
      }
645

  
646
    return -1;
647
    }
648

  
649
///////////////////////////////////////////////////////////////////////////////////////////////////
650
// The Helicopter is solved if and only if:
651
//
652
// 1) all of its corner cubits are rotated with the same quat
653
// 2) all its face cubits are rotated with the same quat like the corner ones,
654
//    and optionally they also might be turned by a multiple of 90 degrees along
655
//    a vector perpendicular to the face they lie on.
656
//
657
// i.e.
658
// cubits  8, 9,10,11,12,13,14,15 - might be extra QUAT 1,8,9
659
// cubits 16,17,18,19,20,21,22,23 - might be extra QUAT 2,12,13
660
// cubits 24,25,26,27,28,29,30,31 - might be extra QUAT 3,14,15
661

  
662
  public boolean isSolved()
663
    {
664
    int q = CUBITS[0].mQuatIndex;
665

  
666
    if ( CUBITS[1].mQuatIndex == q &&
667
         CUBITS[2].mQuatIndex == q &&
668
         CUBITS[3].mQuatIndex == q &&
669
         CUBITS[4].mQuatIndex == q &&
670
         CUBITS[5].mQuatIndex == q &&
671
         CUBITS[6].mQuatIndex == q &&
672
         CUBITS[7].mQuatIndex == q  )
673
      {
674
      int q1 = mulQuat(q,1);
675
      int q2 = mulQuat(q,8);
676
      int q3 = mulQuat(q,9);
677

  
678
      for(int index=8; index<16; index++)
679
        {
680
        int qIndex = CUBITS[index].mQuatIndex;
681
        if( qIndex!=q && qIndex!=q1 && qIndex!=q2 && qIndex!=q3 ) return false;
682
        }
683

  
684
      q1 = mulQuat(q, 2);
685
      q2 = mulQuat(q,12);
686
      q3 = mulQuat(q,13);
687

  
688
      for(int index=16; index<24; index++)
689
        {
690
        int qIndex = CUBITS[index].mQuatIndex;
691
        if( qIndex!=q && qIndex!=q1 && qIndex!=q2 && qIndex!=q3 ) return false;
692
        }
693

  
694
      q1 = mulQuat(q, 3);
695
      q2 = mulQuat(q,14);
696
      q3 = mulQuat(q,15);
697

  
698
      for(int index=24; index<32; index++)
699
        {
700
        int qIndex = CUBITS[index].mQuatIndex;
701
        if( qIndex!=q && qIndex!=q1 && qIndex!=q2 && qIndex!=q3 ) return false;
702
        }
703

  
704
      return true;
705
      }
706

  
707
    return false;
708
    }
709

  
710
///////////////////////////////////////////////////////////////////////////////////////////////////
711
// only needed for solvers - there are no Helicopter solvers ATM)
712

  
713
  public String retObjectString()
714
    {
715
    return "";
716
    }
717

  
718
}
src/main/java/org/distorted/objects/RubikMovementHelicopter.java
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.objects;
21

  
22
///////////////////////////////////////////////////////////////////////////////////////////////////
23

  
24
class RubikMovementHelicopter extends RubikMovement
25
{
26
  RubikMovementHelicopter()
27
    {
28
    super(RubikSkewb.ROT_AXIS, RubikSkewb.FACE_AXIS, 0.25f, 0.25f);
29
    }
30

  
31
///////////////////////////////////////////////////////////////////////////////////////////////////
32
// _____________
33
// |  \  0  /  |
34
// |   \   /   |
35
// | 3 |   | 1 |
36
// |   /   \   |
37
// |  /  2  \  |
38
// -------------
39

  
40
  private int getQuarter(float[] touchPoint)
41
    {
42
    boolean p0 = touchPoint[1] >= touchPoint[0];
43
    boolean p1 = touchPoint[1] >=-touchPoint[0];
44

  
45
    if( p0 )  return p1 ? 0:3;
46
    else      return p1 ? 1:2;
47
    }
48

  
49
///////////////////////////////////////////////////////////////////////////////////////////////////
50

  
51
  boolean isInsideFace(float[] p)
52
    {
53
    return ( p[0]<=0.25f && p[0]>=-0.25f && p[1]<=0.25f && p[1]>=-0.25f );
54
    }
55

  
56
///////////////////////////////////////////////////////////////////////////////////////////////////
57

  
58
  void computeEnabledAxis(int face, float[] touchPoint, int[] enabled)
59
    {
60
    enabled[0] = 2;
61

  
62
    int quarter = getQuarter(touchPoint);
63

  
64
    switch(face)
65
      {
66
      case 0: switch(quarter)
67
                {
68
                case 0: enabled[1]=0; enabled[2]=1; break;
69
                case 1: enabled[1]=3; enabled[2]=1; break;
70
                case 2: enabled[1]=2; enabled[2]=3; break;
71
                case 3: enabled[1]=0; enabled[2]=2; break;
72
                }
73
              break;
74
      case 1: switch(quarter)
75
                {
76
                case 0: enabled[1]=2; enabled[2]=3; break;
77
                case 1: enabled[1]=3; enabled[2]=1; break;
78
                case 2: enabled[1]=0; enabled[2]=1; break;
79
                case 3: enabled[1]=0; enabled[2]=2; break;
80
                }
81
              break;
82
      case 2: switch(quarter)
83
                {
84
                case 0: enabled[1]=1; enabled[2]=2; break;
85
                case 1: enabled[1]=0; enabled[2]=1; break;
86
                case 2: enabled[1]=0; enabled[2]=3; break;
87
                case 3: enabled[1]=2; enabled[2]=3; break;
88
                }
89
              break;
90
      case 3: switch(quarter)
91
                {
92
                case 0: enabled[1]=1; enabled[2]=2; break;
93
                case 1: enabled[1]=2; enabled[2]=3; break;
94
                case 2: enabled[1]=0; enabled[2]=3; break;
95
                case 3: enabled[1]=0; enabled[2]=1; break;
96
                }
97
              break;
98
      case 4: switch(quarter)
99
                {
100
                case 0: enabled[1]=0; enabled[2]=3; break;
101
                case 1: enabled[1]=0; enabled[2]=2; break;
102
                case 2: enabled[1]=1; enabled[2]=2; break;
103
                case 3: enabled[1]=1; enabled[2]=3; break;
104
                }
105
              break;
106
      case 5: switch(quarter)
107
                {
108
                case 0: enabled[1]=1; enabled[2]=2; break;
109
                case 1: enabled[1]=0; enabled[2]=2; break;
110
                case 2: enabled[1]=0; enabled[2]=3; break;
111
                case 3: enabled[1]=1; enabled[2]=3; break;
112
                }
113
              break;
114
      }
115
    }
116
}
src/main/java/org/distorted/objects/RubikObjectList.java
74 74
         new RubikMovementSkewb(),
75 75
         2
76 76
       ),
77

  
78
  HELI (
79
         new int[][] {
80
                       {4 , 18, R.raw.skewb, R.drawable.ui_small_skewb, R.drawable.ui_medium_skewb, R.drawable.ui_big_skewb, R.drawable.ui_huge_skewb} ,
81
                     },
82
         RubikHelicopter.class,
83
         new RubikMovementHelicopter(),
84
         2
85
       ),
77 86
  ;
78 87

  
79 88
  public static final int NUM_OBJECTS = values().length;
......
446 455

  
447 456
    switch(ordinal())
448 457
      {
449
      case 0: return new RubikCube    (size, quat, texture, mesh, effects, moves, res, scrWidth);
450
      case 1: return new RubikPyraminx(size, quat, texture, mesh, effects, moves, res, scrWidth);
451
      case 2: return new RubikDino    (size, quat, texture, mesh, effects, moves, res, scrWidth);
452
      case 3: return new RubikSkewb   (size, quat, texture, mesh, effects, moves, res, scrWidth);
458
      case 0: return new RubikCube      (size, quat, texture, mesh, effects, moves, res, scrWidth);
459
      case 1: return new RubikPyraminx  (size, quat, texture, mesh, effects, moves, res, scrWidth);
460
      case 2: return new RubikDino      (size, quat, texture, mesh, effects, moves, res, scrWidth);
461
      case 3: return new RubikSkewb     (size, quat, texture, mesh, effects, moves, res, scrWidth);
462
      case 4: return new RubikHelicopter(size, quat, texture, mesh, effects, moves, res, scrWidth);
453 463
      }
454 464

  
455 465
    return null;
src/main/java/org/distorted/objects/RubikPyraminx.java
622 622
    }
623 623

  
624 624
///////////////////////////////////////////////////////////////////////////////////////////////////
625
// TODO  (only needed for solvers - there are no Pyraminx solvers ATM)
625
// only needed for solvers - there are no Pyraminx solvers ATM)
626 626

  
627 627
  public String retObjectString()
628 628
    {
src/main/java/org/distorted/objects/RubikSkewb.java
685 685
    }
686 686

  
687 687
///////////////////////////////////////////////////////////////////////////////////////////////////
688
// TODO  (only needed for solvers - there are no Skewb solvers ATM)
688
// only needed for solvers - there are no Skewb solvers ATM)
689 689

  
690 690
  public String retObjectString()
691 691
    {
src/main/res/raw/compute_quats.c
9 9
#define PI  3.14159265358f
10 10
#define NUM_QUATS  100
11 11

  
12
#ifdef PYRAMIX 
12
#ifdef PYRA 
13 13
#define NUM_AXIS    4
14 14
#define BASIC_ANGLE 3
15 15

  
16
float axis[NUM_AXIS][3] ={ {         0,       1,       0 } ,
17
                           { SQ2*SQ3/3, -1.0f/3,  -SQ2/3 } ,
18
                           {-SQ2*SQ3/3, -1.0f/3,  -SQ2/3 } ,
19
                           {         0, -1.0f/3, 2*SQ2/3 } };
16
float axis[NUM_AXIS][3] = { {         0,       1,       0 } ,
17
                            { SQ2*SQ3/3, -1.0f/3,  -SQ2/3 } ,
18
                            {-SQ2*SQ3/3, -1.0f/3,  -SQ2/3 } ,
19
                            {         0, -1.0f/3, 2*SQ2/3 } };
20 20
#endif
21 21

  
22 22
#ifdef CUBE
23 23
#define NUM_AXIS    3
24 24
#define BASIC_ANGLE 4
25 25

  
26
float axis[NUM_AXIS][3] = { { 1,0,0 }, {0,1,0}, {0,0,1} };
26
float axis[NUM_AXIS][3] = { { 1,0,0 } , 
27
                            { 0,1,0 } , 
28
                            { 0,0,1 } };
27 29
#endif
28 30

  
29 31
#ifdef DINO
......
36 38
                            {+SQ3/3,-SQ3/3,-SQ3/3} };
37 39
#endif
38 40

  
39
float* quats;
40
float* table;
41
#ifdef HELI
42
#define NUM_AXIS 6
43
#define BASIC_ANGLE 2
44

  
45
float axis[NUM_AXIS][3] = { {     0, +SQ2/2, -SQ2/2} ,
46
                            {     0, -SQ2/2, -SQ2/2} ,
47
                            {+SQ2/2,      0, -SQ2/2} ,
48
                            {-SQ2/2,      0, -SQ2/2} ,
49
                            {+SQ2/2, -SQ2/2,      0} ,
50
                            {-SQ2/2, -SQ2/2,      0} };
51

  
52
#endif
53

  
41 54
int inserted=0;
42 55

  
43 56
///////////////////////////////////////////////////////////////////
......
117 130
int main(int argc, char** argv)
118 131
  {
119 132
  float tmp[4];
120
  int num = 1+NUM_AXIS*(BASIC_ANGLE-1);
121

  
122
  quats = (float*) malloc(4*sizeof(float)*num      );
123
  table = (float*) malloc(4*sizeof(float)*NUM_QUATS);
133
  float table[4*NUM_QUATS];
134
  int num;
124 135

  
125 136
  tmp[0] = 0.0f; tmp[1] = 0.0f; tmp[2] = 0.0f; tmp[3] = 1.0f;
126
  insert(tmp,quats);
137
  insert(tmp,table);
127 138

  
128 139
  for(int angle=1; angle<BASIC_ANGLE; angle++)
129 140
    for( int ax=0; ax<NUM_AXIS; ax++)
130 141
      {
131 142
      create_quat(axis[ax], 2*PI*angle/BASIC_ANGLE, tmp);
132
      insert(tmp,quats); 
143
      insert(tmp,table); 
133 144
      }
134 145

  
135
  inserted=0;
136

  
137
  for(int i=0; i<num; i++)
138
    for(int j=0; j<num; j++)
139
      {
140
      multiply_quats( quats+4*i, quats+4*j, tmp);
141
      insert(tmp,table);
142
      }
146
  do
147
    {
148
    num = inserted;
149

  
150
    for(int i=0; i<num; i++)
151
      for(int j=0; j<num; j++)
152
        {
153
        multiply_quats( table+4*i, table+4*j, tmp);
154
        insert(tmp,table);
155
        }
156
    }
157
  while( num < inserted );
143 158

  
144 159
  printf("inserted: %d\n", inserted);
145 160

  

Also available in: Unified diff