Project

General

Profile

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

magiccube / src / main / java / org / distorted / objects / RubikHelicopter.java @ 77899b4c

1 ee35e63c Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
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 20a0214b Leszek Koltunski
import org.distorted.library.mesh.MeshTriangle;
38 ee35e63c Leszek Koltunski
import org.distorted.library.type.Static1D;
39
import org.distorted.library.type.Static3D;
40
import org.distorted.library.type.Static4D;
41
import org.distorted.main.RubikSurfaceView;
42
43
import java.util.Random;
44
45
import static org.distorted.effects.scramble.ScrambleEffect.START_AXIS;
46
47
///////////////////////////////////////////////////////////////////////////////////////////////////
48
49
public class RubikHelicopter extends RubikObject
50
{
51
  private static final float SQ2 = (float)Math.sqrt(2);
52
  private static final float SQ3 = (float)Math.sqrt(3);
53
54
  private static final int FACES_PER_CUBIT =6;
55
56
  // the six rotation axis of a Helicopter. Must be normalized.
57
  static final Static3D[] ROT_AXIS = new Static3D[]
58
         {
59
           new Static3D(     0, +SQ2/2, -SQ2/2),
60
           new Static3D(     0, -SQ2/2, -SQ2/2),
61
           new Static3D(+SQ2/2,      0, -SQ2/2),
62
           new Static3D(-SQ2/2,      0, -SQ2/2),
63
           new Static3D(+SQ2/2, -SQ2/2,      0),
64
           new Static3D(-SQ2/2, -SQ2/2,      0)
65
         };
66
67
  // the six axis that determine the faces
68
  static final Static3D[] FACE_AXIS = new Static3D[]
69
         {
70
           new Static3D(1,0,0), new Static3D(-1,0,0),
71
           new Static3D(0,1,0), new Static3D(0,-1,0),
72
           new Static3D(0,0,1), new Static3D(0,0,-1)
73
         };
74
75
  private static final int[] FACE_COLORS = new int[]
76
         {
77
           0xffffff00, 0xffffffff,   // FACE_AXIS[0] (right-YELLOW) FACE_AXIS[1] (left  -WHITE)
78
           0xff0000ff, 0xff00ff00,   // FACE_AXIS[2] (top  -BLUE  ) FACE_AXIS[3] (bottom-GREEN)
79
           0xffff0000, 0xffb5651d    // FACE_AXIS[4] (front-RED   ) FACE_AXIS[5] (back  -BROWN)
80
         };
81
82
  // All legal rotation quats of a HELICOPTER (same as the Cube!)
83
  private static final Static4D[] QUATS = new Static4D[]
84
         {
85
           new Static4D( 0.00f,  0.00f,  0.00f,  1.00f ),
86
           new Static4D( 1.00f,  0.00f,  0.00f,  0.00f ),
87
           new Static4D( 0.00f,  1.00f,  0.00f,  0.00f ),
88
           new Static4D( 0.00f,  0.00f,  1.00f,  0.00f ),
89
90
           new Static4D( SQ2/2,  SQ2/2,  0.00f,  0.00f ),
91
           new Static4D( SQ2/2, -SQ2/2,  0.00f,  0.00f ),
92
           new Static4D( SQ2/2,  0.00f,  SQ2/2,  0.00f ),
93
           new Static4D( SQ2/2,  0.00f, -SQ2/2,  0.00f ),
94
           new Static4D( SQ2/2,  0.00f,  0.00f,  SQ2/2 ),
95
           new Static4D( SQ2/2,  0.00f,  0.00f, -SQ2/2 ),
96
           new Static4D( 0.00f,  SQ2/2,  SQ2/2,  0.00f ),
97
           new Static4D( 0.00f,  SQ2/2, -SQ2/2,  0.00f ),
98
           new Static4D( 0.00f,  SQ2/2,  0.00f,  SQ2/2 ),
99
           new Static4D( 0.00f,  SQ2/2,  0.00f, -SQ2/2 ),
100
           new Static4D( 0.00f,  0.00f,  SQ2/2,  SQ2/2 ),
101
           new Static4D( 0.00f,  0.00f,  SQ2/2, -SQ2/2 ),
102
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
           new Static4D( 0.50f, -0.50f, -0.50f, -0.50f )
111
         };
112
113
  private static final float DIST_CORNER = 0.50f;
114
  private static final float DIST_CENTER = 0.49f;
115
  private static final float XY_CENTER   = DIST_CORNER/3;
116
117
  // centers of the 8 corners + 6*4 face triangles ( i.e. of the all 32 cubits)
118
  private static final Static3D[] CENTERS = new Static3D[]
119
         {
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
           new Static3D(  -DIST_CORNER,  -DIST_CORNER,  -DIST_CORNER ),
128
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
           new Static3D(   DIST_CENTER,    -XY_CENTER,    -XY_CENTER ),
133
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
           new Static3D(  -DIST_CENTER,    -XY_CENTER,    -XY_CENTER ),
138
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
           new Static3D(  -XY_CENTER  ,   DIST_CENTER,    -XY_CENTER ),
143
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
           new Static3D(  -XY_CENTER  ,  -DIST_CENTER,    -XY_CENTER ),
148
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
           new Static3D(  -XY_CENTER  ,    -XY_CENTER,   DIST_CENTER ),
153
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
           new Static3D(  -XY_CENTER  ,    -XY_CENTER,  -DIST_CENTER ),
158
         };
159
160
  // Colors of the faces of cubits. Each cubit has 6 faces
161
  private static final int[][] mFaceMap = new int[][]
162
         {
163
           { 4,2,0, 6,6,6 },
164 20a0214b Leszek Koltunski
           { 0,2,5, 6,6,6 },
165
           { 4,0,3, 6,6,6 },
166 ee35e63c Leszek Koltunski
           { 5,3,0, 6,6,6 },
167
           { 1,2,4, 6,6,6 },
168
           { 5,2,1, 6,6,6 },
169
           { 4,3,1, 6,6,6 },
170
           { 1,3,5, 6,6,6 },
171
172
           { 0 , 6,6,6,6,6 },
173
           { 0 , 6,6,6,6,6 },
174
           { 0 , 6,6,6,6,6 },
175
           { 0 , 6,6,6,6,6 },
176
177
           { 1 , 6,6,6,6,6 },
178
           { 1 , 6,6,6,6,6 },
179
           { 1 , 6,6,6,6,6 },
180
           { 1 , 6,6,6,6,6 },
181
182
           { 2 , 6,6,6,6,6 },
183
           { 2 , 6,6,6,6,6 },
184
           { 2 , 6,6,6,6,6 },
185
           { 2 , 6,6,6,6,6 },
186
187
           { 3 , 6,6,6,6,6 },
188
           { 3 , 6,6,6,6,6 },
189
           { 3 , 6,6,6,6,6 },
190
           { 3 , 6,6,6,6,6 },
191
192
           { 4 , 6,6,6,6,6 },
193
           { 4 , 6,6,6,6,6 },
194
           { 4 , 6,6,6,6,6 },
195
           { 4 , 6,6,6,6,6 },
196
197
           { 5 , 6,6,6,6,6 },
198
           { 5 , 6,6,6,6,6 },
199
           { 5 , 6,6,6,6,6 },
200
           { 5 , 6,6,6,6,6 },
201
         };
202
203 20a0214b Leszek Koltunski
  private static int[] QUAT_INDICES =
204
      { 0,13,14,1,12,2,3,7,20,6,13,17,7,23,18,12,22,10,8,16,11,21,19,9,3,15,14,0,5,2,1,4 };
205
206 ee35e63c Leszek Koltunski
  private static MeshBase mCornerMesh, mFaceMesh;
207
208
///////////////////////////////////////////////////////////////////////////////////////////////////
209
210
  RubikHelicopter(int size, Static4D quat, DistortedTexture texture,
211
                  MeshSquare mesh, DistortedEffects effects, int[][] moves, Resources res, int scrWidth)
212
    {
213
    super(size, 60, quat, texture, mesh, effects, moves, RubikObjectList.HELI, res, scrWidth);
214
    }
215
216
///////////////////////////////////////////////////////////////////////////////////////////////////
217
218
  private void createCornerMesh()
219
    {
220
    float D = 0.02f;
221
    float E = 0.5f;
222
    float F = SQ2/4;
223
224
    float[] vertices0 = { -E+E/4,E/4, E/4,-E+E/4, E/4,E/4};
225
226
    float[] bands0 = { 1.0f    , 0,
227
                       1.0f-2*D, D*0.25f,
228
                       1.0f-4*D, D*0.35f,
229
                       1.0f-8*D, D*0.6f,
230
                       0.60f   , D*1.0f,
231
                       0.30f   , D*1.375f,
232
                       0.0f    , D*1.4f };
233
234
    MeshBase[] meshes = new MeshBase[6];
235
236
    meshes[0] = new MeshPolygon(vertices0, bands0, 3, 3);
237
    meshes[0].setEffectAssociation(0,1,0);
238
    meshes[1] = meshes[0].copy(true);
239
    meshes[1].setEffectAssociation(0,2,0);
240
    meshes[2] = meshes[0].copy(true);
241
    meshes[2].setEffectAssociation(0,4,0);
242
243
    float[] vertices1 = { -F,-1.0f/12, +F,-1.0f/12, 0,1.0f/6 };
244
    float[] bands1 = { 1.0f, 0.0f, 0.5f, 0.0f, 0.0f, 0.0f };
245
246 20a0214b Leszek Koltunski
    meshes[3] = new MeshPolygon(vertices1,bands1,1,5);
247 ee35e63c Leszek Koltunski
    meshes[3].setEffectAssociation(0,8,0);
248
    meshes[4] = meshes[3].copy(true);
249
    meshes[4].setEffectAssociation(0,16,0);
250
    meshes[5] = meshes[3].copy(true);
251
    meshes[5].setEffectAssociation(0,32,0);
252
253
    mCornerMesh = new MeshJoined(meshes);
254
255
    Static3D axisX  = new Static3D(1,0,0);
256
    Static3D axisY  = new Static3D(0,1,0);
257
    Static3D axis0  = new Static3D(-SQ2/2,0,SQ2/2);
258
    Static3D axis1  = new Static3D(+SQ3/3,+SQ3/3,+SQ3/3);
259
    Static1D angle1 = new Static1D(+90);
260
    Static1D angle2 = new Static1D(-90);
261
    Static1D angle3 = new Static1D(-135);
262
    Static1D angle4 = new Static1D(90);
263
    Static1D angle5 = new Static1D(120);
264
    Static1D angle6 = new Static1D(240);
265
    Static3D center1= new Static3D(0,0,0);
266
    Static3D center2= new Static3D(-0.25f,-0.25f,-0.25f);
267
    Static3D move1  = new Static3D(-E/4,-E/4,0);
268
    Static3D move2  = new Static3D(-0.25f,(-1.0f/6)-0.25f,-0.25f);
269
270
    float d0 =-0.04f;
271
    float d1 = 0.04f;
272
    float r0 = 0.15f;
273
    float r1 = 0.10f;
274
275
    Static3D vec0   = new Static3D(d0*(+SQ3/3),d0*(+SQ3/3),d0*(+SQ3/3));
276
    Static3D vec1   = new Static3D(d1*(+SQ3/3),d1*(-SQ3/3),d1*(-SQ3/3));
277
    Static3D vec2   = new Static3D(d1*(-SQ3/3),d1*(+SQ3/3),d1*(-SQ3/3));
278
    Static3D vec3   = new Static3D(d1*(-SQ3/3),d1*(-SQ3/3),d1*(+SQ3/3));
279
280
    Static1D radius = new Static1D(0.5f);
281
282
    Static3D cent0  = new Static3D( 0.0f, 0.0f, 0.0f);
283
    Static3D cent1  = new Static3D(-0.5f, 0.0f, 0.0f);
284
    Static3D cent2  = new Static3D( 0.0f,-0.5f, 0.0f);
285
    Static3D cent3  = new Static3D( 0.0f, 0.0f,-0.5f);
286
287
    Static4D reg0   = new Static4D(0,0,0,r0);
288
    Static4D reg1   = new Static4D(0,0,0,r1);
289
290
    VertexEffectMove   effect0 = new VertexEffectMove(move1);
291
    VertexEffectScale  effect1 = new VertexEffectScale(new Static3D(1,1,-1));
292
    VertexEffectRotate effect2 = new VertexEffectRotate(angle1,axisX,center1);
293
    VertexEffectRotate effect3 = new VertexEffectRotate(angle2,axisY,center1);
294
    VertexEffectMove   effect4 = new VertexEffectMove(move2);
295
    VertexEffectRotate effect5 = new VertexEffectRotate(angle1,axisX,center2);
296
    VertexEffectRotate effect6 = new VertexEffectRotate(angle3,axisY,center2);
297
    VertexEffectRotate effect7 = new VertexEffectRotate(angle4,axis0,center2);
298
    VertexEffectRotate effect8 = new VertexEffectRotate(angle5,axis1,center2);
299
    VertexEffectRotate effect9 = new VertexEffectRotate(angle6,axis1,center2);
300
301
    VertexEffectDeform effect10= new VertexEffectDeform(vec0,radius,cent0,reg0);
302
    VertexEffectDeform effect11= new VertexEffectDeform(vec1,radius,cent1,reg1);
303
    VertexEffectDeform effect12= new VertexEffectDeform(vec2,radius,cent2,reg1);
304
    VertexEffectDeform effect13= new VertexEffectDeform(vec3,radius,cent3,reg1);
305
306
    effect0.setMeshAssociation( 7,-1);  // meshes 0,1,2
307
    effect1.setMeshAssociation( 6,-1);  // meshes 1,2
308
    effect2.setMeshAssociation( 2,-1);  // mesh 1
309
    effect3.setMeshAssociation( 4,-1);  // mesh 2
310
    effect4.setMeshAssociation(56,-1);  // meshes 3,4,5
311
    effect5.setMeshAssociation(56,-1);  // meshes 3,4,5
312
    effect6.setMeshAssociation(56,-1);  // meshes 3,4,5
313
    effect7.setMeshAssociation(56,-1);  // meshes 3,4,5
314
    effect8.setMeshAssociation(16,-1);  // mesh 4
315
    effect9.setMeshAssociation(32,-1);  // mesh 5
316
317
    effect10.setMeshAssociation(63,-1); // all meshes
318
    effect11.setMeshAssociation(63,-1); // all meshes
319
    effect12.setMeshAssociation(63,-1); // all meshes
320
    effect13.setMeshAssociation(63,-1); // all meshes
321
322
    mCornerMesh.apply(effect0);
323
    mCornerMesh.apply(effect1);
324
    mCornerMesh.apply(effect2);
325
    mCornerMesh.apply(effect3);
326
    mCornerMesh.apply(effect4);
327
    mCornerMesh.apply(effect5);
328
    mCornerMesh.apply(effect6);
329
    mCornerMesh.apply(effect7);
330
    mCornerMesh.apply(effect8);
331
    mCornerMesh.apply(effect9);
332
333
    mCornerMesh.apply(effect10);
334
    mCornerMesh.apply(effect11);
335
    mCornerMesh.apply(effect12);
336
    mCornerMesh.apply(effect13);
337
338
    mCornerMesh.mergeEffComponents();
339
    }
340
341
///////////////////////////////////////////////////////////////////////////////////////////////////
342
343
  private void createFaceMesh()
344
    {
345 20a0214b Leszek Koltunski
    MeshBase[] meshes = new MeshBase[6];
346
347 ee35e63c Leszek Koltunski
    float D = 0.02f;
348
    float E = 0.5f;
349
    float F = SQ2/4;
350 20a0214b Leszek Koltunski
    float G = 1.0f/12;
351 ee35e63c Leszek Koltunski
352
    float[] vertices0 = { -E+E/4,E/4, E/4,-E+E/4, E/4,E/4};
353
354
    float[] bands0 = { 1.0f    , 0,
355
                       1.0f-2*D, D*0.25f,
356
                       1.0f-4*D, D*0.35f,
357
                       1.0f-8*D, D*0.6f,
358
                       0.60f   , D*1.0f,
359
                       0.30f   , D*1.375f,
360
                       0.0f    , D*1.4f };
361
362
    meshes[0] = new MeshPolygon(vertices0, bands0, 3, 3);
363
    meshes[0].setEffectAssociation(0,1,0);
364
365 20a0214b Leszek Koltunski
    float[] vertices1 = { -F,-G, +F,-G, 0,2*G};
366
367
    float[] bands1 = { 1.0f   , 0.0f,
368 77899b4c Leszek Koltunski
                       0.5f   , 0.01f,
369
                       0.0f   , 0.01f };
370 20a0214b Leszek Koltunski
371
    meshes[1] = new MeshPolygon(vertices1, bands1, 1, 3);
372
    meshes[1].setEffectAssociation(0,2,0);
373
374
    float[] vertices2 = { -E/2,-F/3, +E/2,-F/3, 0,2*F/3};
375
376
    float[] bands2 = { 1.0f   , 0.0f,
377
                       0.5f   , 0.02f,
378
                       0.0f   , 0.03f };
379
380
    meshes[2] = new MeshPolygon(vertices2, bands2, 1, 3);
381
    meshes[2].setEffectAssociation(0,4,0);
382
    meshes[3] = meshes[2].copy(true);
383
    meshes[3].setEffectAssociation(0,8,0);
384
    meshes[4] = new MeshTriangle(1);
385
    meshes[4].setEffectAssociation(0,16,0);
386
    meshes[5] = new MeshTriangle(1);
387
    meshes[5].setEffectAssociation(0,32,0);
388
389
    mFaceMesh = new MeshJoined(meshes);
390
391
    Static3D move0  = new Static3D(-1.0f/8, -1.0f/8, 0);
392
    Static3D move1  = new Static3D(-(SQ2/24)-1.0f/4, -(SQ2/24)-1.0f/4, 0);
393
    Static3D move2  = new Static3D(-E/2, F/3, 0);
394
    Static3D move3  = new Static3D(+E/2, F/3, 0);
395
    Static3D move4  = new Static3D(+E/3,+E/3, 0);
396
    Static1D angle1 = new Static1D(135);
397
    Static1D angle2 = new Static1D(90);
398
    Static1D angle3 = new Static1D(-90);
399
    Static1D angle4 = new Static1D(-135);
400
    Static3D axisX  = new Static3D(1,0,0);
401
    Static3D axisY  = new Static3D(0,1,0);
402
    Static3D axisZ  = new Static3D(0,0,1);
403
    Static3D axis1  = new Static3D(1,-1,0);
404
    Static3D center = new Static3D(0,0,0);
405
    Static3D center1= new Static3D(-0.25f,-0.25f,0);
406
407 77899b4c Leszek Koltunski
    float d0 =-0.03f;
408 20a0214b Leszek Koltunski
    float d1 =-0.04f;
409
    float r0 = 0.15f;
410
    float r1 = 0.10f;
411
412
    Static3D vec0   = new Static3D(d0*(+SQ3/3),d0*(+SQ3/3),d0*(+SQ3/3));
413
    Static3D vec1   = new Static3D(d1*(-SQ3/3),d1*(+SQ3/3),d1*(+SQ3/3));
414
    Static3D vec2   = new Static3D(d1*(+SQ3/3),d1*(-SQ3/3),d1*(+SQ3/3));
415
416
    Static1D radius = new Static1D(0.5f);
417
418
    Static3D cent0  = new Static3D( 0.0f, 0.0f, 0.0f);
419
    Static3D cent1  = new Static3D(-0.5f, 0.0f, 0.0f);
420
    Static3D cent2  = new Static3D( 0.0f,-0.5f, 0.0f);
421
422
    Static4D reg0   = new Static4D(0,0,0,r0);
423
    Static4D reg1   = new Static4D(0,0,0,r1);
424
425
    VertexEffectMove   effect0 = new VertexEffectMove(move0);
426
    VertexEffectRotate effect1 = new VertexEffectRotate(angle1, axisZ, center);
427
    VertexEffectMove   effect2 = new VertexEffectMove(move1);
428
    VertexEffectRotate effect3 = new VertexEffectRotate(angle2, axis1, center1);
429
    VertexEffectMove   effect4 = new VertexEffectMove(move2);
430
    VertexEffectMove   effect5 = new VertexEffectMove(move3);
431
    VertexEffectRotate effect6 = new VertexEffectRotate(angle3, axisZ, center);
432
    VertexEffectRotate effect7 = new VertexEffectRotate(angle4, axisX, center);
433
    VertexEffectRotate effect8 = new VertexEffectRotate(angle1, axisY, center);
434
    VertexEffectScale  effect9 = new VertexEffectScale(0);
435
    VertexEffectDeform effect10= new VertexEffectDeform(vec0,radius,cent0,reg0);
436
    VertexEffectDeform effect11= new VertexEffectDeform(vec1,radius,cent1,reg1);
437
    VertexEffectDeform effect12= new VertexEffectDeform(vec2,radius,cent2,reg1);
438
    VertexEffectMove   effect13= new VertexEffectMove(move4);
439
440
    effect0.setMeshAssociation( 1,-1);  // mesh 0
441
    effect1.setMeshAssociation( 2,-1);  // mesh 1
442
    effect2.setMeshAssociation( 2,-1);  // mesh 1
443
    effect3.setMeshAssociation( 2,-1);  // mesh 1
444
    effect4.setMeshAssociation( 4,-1);  // mesh 2
445
    effect5.setMeshAssociation( 8,-1);  // mesh 3
446
    effect6.setMeshAssociation( 8,-1);  // mesh 3
447
    effect7.setMeshAssociation( 4,-1);  // mesh 2
448
    effect8.setMeshAssociation( 8,-1);  // mesh 3
449
    effect9.setMeshAssociation(48,-1);  // meshes 4,5
450
    effect10.setMeshAssociation(15,-1); // meshes 0,1,2,3
451
    effect11.setMeshAssociation(15,-1); // meshes 0,1,2,3
452
    effect12.setMeshAssociation(15,-1); // meshes 0,1,2,3
453
    effect13.setMeshAssociation(15,-1); // meshes 0,1,2,3
454
455
    mFaceMesh.apply(effect0);
456
    mFaceMesh.apply(effect1);
457
    mFaceMesh.apply(effect2);
458
    mFaceMesh.apply(effect3);
459
    mFaceMesh.apply(effect4);
460
    mFaceMesh.apply(effect5);
461
    mFaceMesh.apply(effect6);
462
    mFaceMesh.apply(effect7);
463
    mFaceMesh.apply(effect8);
464
    mFaceMesh.apply(effect9);
465
    mFaceMesh.apply(effect10);
466
    mFaceMesh.apply(effect11);
467
    mFaceMesh.apply(effect12);
468
    mFaceMesh.apply(effect13);
469 ee35e63c Leszek Koltunski
470
    mFaceMesh.mergeEffComponents();
471
    }
472
473
///////////////////////////////////////////////////////////////////////////////////////////////////
474
475
  float getScreenRatio()
476
    {
477 20a0214b Leszek Koltunski
    return 2.0f;
478 ee35e63c Leszek Koltunski
    }
479
480
///////////////////////////////////////////////////////////////////////////////////////////////////
481
482
  Static4D[] getQuats()
483
    {
484
    return QUATS;
485
    }
486
487
///////////////////////////////////////////////////////////////////////////////////////////////////
488
489
  int getNumFaces()
490
    {
491
    return FACE_COLORS.length;
492
    }
493
494
///////////////////////////////////////////////////////////////////////////////////////////////////
495
496
  int getNumStickerTypes()
497
    {
498
    return 1;
499
    }
500
501
///////////////////////////////////////////////////////////////////////////////////////////////////
502
503
  int getNumCubitFaces()
504
    {
505
    return FACES_PER_CUBIT;
506
    }
507
508
///////////////////////////////////////////////////////////////////////////////////////////////////
509
510
  Static3D[] getCubitPositions(int size)
511
    {
512
    return CENTERS;
513
    }
514
515
///////////////////////////////////////////////////////////////////////////////////////////////////
516
517
  MeshBase createCubitMesh(int cubit)
518
    {
519
    MeshBase mesh;
520
521
    if( cubit<8 )
522
      {
523
      if( mCornerMesh==null ) createCornerMesh();
524
      mesh = mCornerMesh.copy(true);
525
      }
526
    else
527
      {
528
      if( mFaceMesh==null ) createFaceMesh();
529
      mesh = mFaceMesh.copy(true);
530
      }
531
532 20a0214b Leszek Koltunski
    int index = QUAT_INDICES[cubit];
533 ee35e63c Leszek Koltunski
    MatrixEffectQuaternion quat = new MatrixEffectQuaternion( QUATS[index], new Static3D(0,0,0) );
534
    mesh.apply(quat,0xffffffff,0);
535
536
    return mesh;
537
    }
538
539
///////////////////////////////////////////////////////////////////////////////////////////////////
540
541
  int getFaceColor(int cubit, int cubitface, int size)
542
    {
543
    return mFaceMap[cubit][cubitface];
544
    }
545
546
///////////////////////////////////////////////////////////////////////////////////////////////////
547
548
  void createFaceTexture(Canvas canvas, Paint paint, int face, int left, int top, int side)
549
    {
550
    float STROKE = 0.035f*side;
551
    float L= left+0.125f*side;
552
    float H= 0.375f*side;
553
    float LEN = 0.5f*side;
554
555
    paint.setAntiAlias(true);
556
    paint.setStrokeWidth(STROKE);
557
    paint.setColor(FACE_COLORS[face]);
558
    paint.setStyle(Paint.Style.FILL);
559
560
    canvas.drawRect(left,top,left+side,top+side,paint);
561
562
    paint.setColor(INTERIOR_COLOR);
563
    paint.setStyle(Paint.Style.STROKE);
564
565
    canvas.drawLine( L    , H,  L+LEN, H    , paint);
566
    canvas.drawLine( L    , H,  L+LEN, H+LEN, paint);
567
    canvas.drawLine( L+LEN, H,  L+LEN, H+LEN, paint);
568
569
    float S1 = 0.125f*side;
570
    float S2 = 0.070f*side;
571
    float X  = 0.7f*S2;
572
573
    float LA = left+0.625f*side;
574
    float RA = left+0.125f*side;
575
    float TA = 0.375f*side;
576
    float BA = 0.875f*side;
577
578
    canvas.drawArc( LA-S1, TA     , LA     , TA+S1, 270, 90, false, paint);
579
    canvas.drawArc( RA+X , TA     , RA+X+S2, TA+S2, 135,135, false, paint);
580
    canvas.drawArc( LA-S2, BA-X-S2, LA     , BA-X ,   0,135, false, paint);
581
    }
582
583
///////////////////////////////////////////////////////////////////////////////////////////////////
584
585
  float returnMultiplier()
586
    {
587
    return 2.0f;
588
    }
589
590
///////////////////////////////////////////////////////////////////////////////////////////////////
591
592
  float[] getRowChances()
593
    {
594
    float[] chances = new float[4];
595
596
    chances[0] = 0.5f;
597
    chances[1] = 0.5f;
598
    chances[2] = 0.5f;
599
    chances[3] = 1.0f;
600
601
    return chances;
602
    }
603
604
///////////////////////////////////////////////////////////////////////////////////////////////////
605
// PUBLIC API
606
607
  public Static3D[] getRotationAxis()
608
    {
609
    return ROT_AXIS;
610
    }
611
612
///////////////////////////////////////////////////////////////////////////////////////////////////
613
614
  public int getBasicAngle()
615
    {
616
    return 2;
617
    }
618
619
///////////////////////////////////////////////////////////////////////////////////////////////////
620
621
  public int computeRowFromOffset(float offset)
622
    {
623 77899b4c Leszek Koltunski
    return offset<0.125f ? 0:3;
624 ee35e63c Leszek Koltunski
    }
625
626
///////////////////////////////////////////////////////////////////////////////////////////////////
627
628
  public float returnRotationFactor(float offset)
629
    {
630
    return 1.0f;
631
    }
632
633
///////////////////////////////////////////////////////////////////////////////////////////////////
634
635
  public int randomizeNewRotAxis(Random rnd, int oldRotAxis)
636
    {
637
    int numAxis = ROTATION_AXIS.length;
638
639
    if( oldRotAxis == START_AXIS )
640
      {
641
      return rnd.nextInt(numAxis);
642
      }
643
    else
644
      {
645
      int newVector = rnd.nextInt(numAxis-2);
646
647
      switch(oldRotAxis)
648
        {
649
        case  0:
650
        case  1: return newVector+2;
651
        case  2:
652
        case  3: return (newVector==0 || newVector==1) ? newVector:newVector+2;
653
        default: return newVector;
654
        }
655
      }
656
    }
657
658
///////////////////////////////////////////////////////////////////////////////////////////////////
659
660
  public int randomizeNewRow(Random rnd, int oldRotAxis, int oldRow, int newRotAxis)
661
    {
662
    float rowFloat = rnd.nextFloat();
663
664
    for(int row=0; row<mRowChances.length; row++)
665
      {
666
      if( rowFloat<=mRowChances[row] ) return row;
667
      }
668
669
    return 0;
670
    }
671
672
///////////////////////////////////////////////////////////////////////////////////////////////////
673
// remember about the double cover or unit quaternions!
674
675
  private int mulQuat(int q1, int q2)
676
    {
677
    Static4D result = RubikSurfaceView.quatMultiply(QUATS[q1],QUATS[q2]);
678
679
    float rX = result.get0();
680
    float rY = result.get1();
681
    float rZ = result.get2();
682
    float rW = result.get3();
683
684
    final float MAX_ERROR = 0.1f;
685
    float dX,dY,dZ,dW;
686
687
    for(int i=0; i<QUATS.length; i++)
688
      {
689
      dX = QUATS[i].get0() - rX;
690
      dY = QUATS[i].get1() - rY;
691
      dZ = QUATS[i].get2() - rZ;
692
      dW = QUATS[i].get3() - rW;
693
694
      if( dX<MAX_ERROR && dX>-MAX_ERROR &&
695
          dY<MAX_ERROR && dY>-MAX_ERROR &&
696
          dZ<MAX_ERROR && dZ>-MAX_ERROR &&
697
          dW<MAX_ERROR && dW>-MAX_ERROR  ) return i;
698
699
      dX = QUATS[i].get0() + rX;
700
      dY = QUATS[i].get1() + rY;
701
      dZ = QUATS[i].get2() + rZ;
702
      dW = QUATS[i].get3() + rW;
703
704
      if( dX<MAX_ERROR && dX>-MAX_ERROR &&
705
          dY<MAX_ERROR && dY>-MAX_ERROR &&
706
          dZ<MAX_ERROR && dZ>-MAX_ERROR &&
707
          dW<MAX_ERROR && dW>-MAX_ERROR  ) return i;
708
      }
709
710
    return -1;
711
    }
712
713
///////////////////////////////////////////////////////////////////////////////////////////////////
714
// The Helicopter is solved if and only if:
715
//
716
// 1) all of its corner cubits are rotated with the same quat
717
// 2) all its face cubits are rotated with the same quat like the corner ones,
718
//    and optionally they also might be turned by a multiple of 90 degrees along
719
//    a vector perpendicular to the face they lie on.
720
//
721
// i.e.
722
// cubits  8, 9,10,11,12,13,14,15 - might be extra QUAT 1,8,9
723
// cubits 16,17,18,19,20,21,22,23 - might be extra QUAT 2,12,13
724
// cubits 24,25,26,27,28,29,30,31 - might be extra QUAT 3,14,15
725
726
  public boolean isSolved()
727
    {
728
    int q = CUBITS[0].mQuatIndex;
729
730
    if ( CUBITS[1].mQuatIndex == q &&
731
         CUBITS[2].mQuatIndex == q &&
732
         CUBITS[3].mQuatIndex == q &&
733
         CUBITS[4].mQuatIndex == q &&
734
         CUBITS[5].mQuatIndex == q &&
735
         CUBITS[6].mQuatIndex == q &&
736
         CUBITS[7].mQuatIndex == q  )
737
      {
738
      int q1 = mulQuat(q,1);
739
      int q2 = mulQuat(q,8);
740
      int q3 = mulQuat(q,9);
741
742
      for(int index=8; index<16; index++)
743
        {
744
        int qIndex = CUBITS[index].mQuatIndex;
745
        if( qIndex!=q && qIndex!=q1 && qIndex!=q2 && qIndex!=q3 ) return false;
746
        }
747
748
      q1 = mulQuat(q, 2);
749
      q2 = mulQuat(q,12);
750
      q3 = mulQuat(q,13);
751
752
      for(int index=16; index<24; index++)
753
        {
754
        int qIndex = CUBITS[index].mQuatIndex;
755
        if( qIndex!=q && qIndex!=q1 && qIndex!=q2 && qIndex!=q3 ) return false;
756
        }
757
758
      q1 = mulQuat(q, 3);
759
      q2 = mulQuat(q,14);
760
      q3 = mulQuat(q,15);
761
762
      for(int index=24; index<32; index++)
763
        {
764
        int qIndex = CUBITS[index].mQuatIndex;
765
        if( qIndex!=q && qIndex!=q1 && qIndex!=q2 && qIndex!=q3 ) return false;
766
        }
767
768
      return true;
769
      }
770
771
    return false;
772
    }
773
774
///////////////////////////////////////////////////////////////////////////////////////////////////
775
// only needed for solvers - there are no Helicopter solvers ATM)
776
777
  public String retObjectString()
778
    {
779
    return "";
780
    }
781
782
}