Project

General

Profile

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

magiccube / src / main / java / org / distorted / objects / RubikHelicopter.java @ 3717a94e

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 b0a56742 Leszek Koltunski
  private static final float DIST_CENTER = 0.50f;
115 ee35e63c Leszek Koltunski
  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 b0a56742 Leszek Koltunski
                       0.5f   , 0.01f,
378
                       0.0f   , 0.01f };
379 20a0214b Leszek Koltunski
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 7403cdfa Leszek Koltunski
    return 1.5f;
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 7403cdfa Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
502
503
  float getBasicStep()
504
    {
505
    return SQ2/2;
506
    }
507
508 ee35e63c Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
509
510
  int getNumCubitFaces()
511
    {
512
    return FACES_PER_CUBIT;
513
    }
514
515
///////////////////////////////////////////////////////////////////////////////////////////////////
516
517
  Static3D[] getCubitPositions(int size)
518
    {
519
    return CENTERS;
520
    }
521
522
///////////////////////////////////////////////////////////////////////////////////////////////////
523
524
  MeshBase createCubitMesh(int cubit)
525
    {
526
    MeshBase mesh;
527
528
    if( cubit<8 )
529
      {
530
      if( mCornerMesh==null ) createCornerMesh();
531
      mesh = mCornerMesh.copy(true);
532
      }
533
    else
534
      {
535
      if( mFaceMesh==null ) createFaceMesh();
536
      mesh = mFaceMesh.copy(true);
537
      }
538
539 20a0214b Leszek Koltunski
    int index = QUAT_INDICES[cubit];
540 ee35e63c Leszek Koltunski
    MatrixEffectQuaternion quat = new MatrixEffectQuaternion( QUATS[index], new Static3D(0,0,0) );
541
    mesh.apply(quat,0xffffffff,0);
542
543
    return mesh;
544
    }
545
546
///////////////////////////////////////////////////////////////////////////////////////////////////
547
548
  int getFaceColor(int cubit, int cubitface, int size)
549
    {
550
    return mFaceMap[cubit][cubitface];
551
    }
552
553
///////////////////////////////////////////////////////////////////////////////////////////////////
554
555
  void createFaceTexture(Canvas canvas, Paint paint, int face, int left, int top, int side)
556
    {
557
    float STROKE = 0.035f*side;
558
    float L= left+0.125f*side;
559
    float H= 0.375f*side;
560
    float LEN = 0.5f*side;
561
562
    paint.setAntiAlias(true);
563
    paint.setStrokeWidth(STROKE);
564
    paint.setColor(FACE_COLORS[face]);
565
    paint.setStyle(Paint.Style.FILL);
566
567
    canvas.drawRect(left,top,left+side,top+side,paint);
568
569
    paint.setColor(INTERIOR_COLOR);
570
    paint.setStyle(Paint.Style.STROKE);
571
572
    canvas.drawLine( L    , H,  L+LEN, H    , paint);
573
    canvas.drawLine( L    , H,  L+LEN, H+LEN, paint);
574
    canvas.drawLine( L+LEN, H,  L+LEN, H+LEN, paint);
575
576
    float S1 = 0.125f*side;
577
    float S2 = 0.070f*side;
578
    float X  = 0.7f*S2;
579
580
    float LA = left+0.625f*side;
581
    float RA = left+0.125f*side;
582
    float TA = 0.375f*side;
583
    float BA = 0.875f*side;
584
585
    canvas.drawArc( LA-S1, TA     , LA     , TA+S1, 270, 90, false, paint);
586
    canvas.drawArc( RA+X , TA     , RA+X+S2, TA+S2, 135,135, false, paint);
587
    canvas.drawArc( LA-S2, BA-X-S2, LA     , BA-X ,   0,135, false, paint);
588
    }
589
590
///////////////////////////////////////////////////////////////////////////////////////////////////
591
592
  float returnMultiplier()
593
    {
594
    return 2.0f;
595
    }
596
597
///////////////////////////////////////////////////////////////////////////////////////////////////
598
599
  float[] getRowChances()
600
    {
601 475cbfe7 Leszek Koltunski
    float[] chances = new float[3];
602 ee35e63c Leszek Koltunski
603
    chances[0] = 0.5f;
604
    chances[1] = 0.5f;
605 475cbfe7 Leszek Koltunski
    chances[2] = 1.0f;
606 ee35e63c Leszek Koltunski
607
    return chances;
608
    }
609
610
///////////////////////////////////////////////////////////////////////////////////////////////////
611
// PUBLIC API
612
613
  public Static3D[] getRotationAxis()
614
    {
615
    return ROT_AXIS;
616
    }
617
618
///////////////////////////////////////////////////////////////////////////////////////////////////
619
620
  public int getBasicAngle()
621
    {
622
    return 2;
623
    }
624
625
///////////////////////////////////////////////////////////////////////////////////////////////////
626
627
  public int computeRowFromOffset(float offset)
628
    {
629 7403cdfa Leszek Koltunski
    return offset<0.166f ? 0:2;
630 ee35e63c Leszek Koltunski
    }
631
632
///////////////////////////////////////////////////////////////////////////////////////////////////
633
634
  public float returnRotationFactor(float offset)
635
    {
636
    return 1.0f;
637
    }
638
639
///////////////////////////////////////////////////////////////////////////////////////////////////
640
641
  public int randomizeNewRotAxis(Random rnd, int oldRotAxis)
642
    {
643
    int numAxis = ROTATION_AXIS.length;
644
645
    if( oldRotAxis == START_AXIS )
646
      {
647
      return rnd.nextInt(numAxis);
648
      }
649
    else
650
      {
651
      int newVector = rnd.nextInt(numAxis-2);
652
653
      switch(oldRotAxis)
654
        {
655
        case  0:
656
        case  1: return newVector+2;
657
        case  2:
658
        case  3: return (newVector==0 || newVector==1) ? newVector:newVector+2;
659
        default: return newVector;
660
        }
661
      }
662
    }
663
664
///////////////////////////////////////////////////////////////////////////////////////////////////
665
666
  public int randomizeNewRow(Random rnd, int oldRotAxis, int oldRow, int newRotAxis)
667
    {
668
    float rowFloat = rnd.nextFloat();
669
670
    for(int row=0; row<mRowChances.length; row++)
671
      {
672
      if( rowFloat<=mRowChances[row] ) return row;
673
      }
674
675
    return 0;
676
    }
677
678
///////////////////////////////////////////////////////////////////////////////////////////////////
679
// remember about the double cover or unit quaternions!
680
681
  private int mulQuat(int q1, int q2)
682
    {
683
    Static4D result = RubikSurfaceView.quatMultiply(QUATS[q1],QUATS[q2]);
684
685
    float rX = result.get0();
686
    float rY = result.get1();
687
    float rZ = result.get2();
688
    float rW = result.get3();
689
690
    final float MAX_ERROR = 0.1f;
691
    float dX,dY,dZ,dW;
692
693
    for(int i=0; i<QUATS.length; i++)
694
      {
695
      dX = QUATS[i].get0() - rX;
696
      dY = QUATS[i].get1() - rY;
697
      dZ = QUATS[i].get2() - rZ;
698
      dW = QUATS[i].get3() - rW;
699
700
      if( dX<MAX_ERROR && dX>-MAX_ERROR &&
701
          dY<MAX_ERROR && dY>-MAX_ERROR &&
702
          dZ<MAX_ERROR && dZ>-MAX_ERROR &&
703
          dW<MAX_ERROR && dW>-MAX_ERROR  ) return i;
704
705
      dX = QUATS[i].get0() + rX;
706
      dY = QUATS[i].get1() + rY;
707
      dZ = QUATS[i].get2() + rZ;
708
      dW = QUATS[i].get3() + rW;
709
710
      if( dX<MAX_ERROR && dX>-MAX_ERROR &&
711
          dY<MAX_ERROR && dY>-MAX_ERROR &&
712
          dZ<MAX_ERROR && dZ>-MAX_ERROR &&
713
          dW<MAX_ERROR && dW>-MAX_ERROR  ) return i;
714
      }
715
716
    return -1;
717
    }
718
719
///////////////////////////////////////////////////////////////////////////////////////////////////
720
// The Helicopter is solved if and only if:
721
//
722
// 1) all of its corner cubits are rotated with the same quat
723
// 2) all its face cubits are rotated with the same quat like the corner ones,
724
//    and optionally they also might be turned by a multiple of 90 degrees along
725
//    a vector perpendicular to the face they lie on.
726
//
727
// i.e.
728
// cubits  8, 9,10,11,12,13,14,15 - might be extra QUAT 1,8,9
729
// cubits 16,17,18,19,20,21,22,23 - might be extra QUAT 2,12,13
730
// cubits 24,25,26,27,28,29,30,31 - might be extra QUAT 3,14,15
731
732
  public boolean isSolved()
733
    {
734
    int q = CUBITS[0].mQuatIndex;
735
736
    if ( CUBITS[1].mQuatIndex == q &&
737
         CUBITS[2].mQuatIndex == q &&
738
         CUBITS[3].mQuatIndex == q &&
739
         CUBITS[4].mQuatIndex == q &&
740
         CUBITS[5].mQuatIndex == q &&
741
         CUBITS[6].mQuatIndex == q &&
742
         CUBITS[7].mQuatIndex == q  )
743
      {
744
      int q1 = mulQuat(q,1);
745
      int q2 = mulQuat(q,8);
746
      int q3 = mulQuat(q,9);
747
748
      for(int index=8; index<16; index++)
749
        {
750
        int qIndex = CUBITS[index].mQuatIndex;
751
        if( qIndex!=q && qIndex!=q1 && qIndex!=q2 && qIndex!=q3 ) return false;
752
        }
753
754
      q1 = mulQuat(q, 2);
755
      q2 = mulQuat(q,12);
756
      q3 = mulQuat(q,13);
757
758
      for(int index=16; index<24; index++)
759
        {
760
        int qIndex = CUBITS[index].mQuatIndex;
761
        if( qIndex!=q && qIndex!=q1 && qIndex!=q2 && qIndex!=q3 ) return false;
762
        }
763
764
      q1 = mulQuat(q, 3);
765
      q2 = mulQuat(q,14);
766
      q3 = mulQuat(q,15);
767
768
      for(int index=24; index<32; index++)
769
        {
770
        int qIndex = CUBITS[index].mQuatIndex;
771
        if( qIndex!=q && qIndex!=q1 && qIndex!=q2 && qIndex!=q3 ) return false;
772
        }
773
774
      return true;
775
      }
776
777
    return false;
778
    }
779
780
///////////////////////////////////////////////////////////////////////////////////////////////////
781
// only needed for solvers - there are no Helicopter solvers ATM)
782
783
  public String retObjectString()
784
    {
785
    return "";
786
    }
787
788
}