Project

General

Profile

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

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

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.mesh.MeshTriangle;
38
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
           { 0,2,5, 6,6,6 },
165
           { 4,0,3, 6,6,6 },
166
           { 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
  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
  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
    meshes[3] = new MeshPolygon(vertices1,bands1,1,5);
247
    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
    MeshBase[] meshes = new MeshBase[6];
346

    
347
    float D = 0.02f;
348
    float E = 0.5f;
349
    float F = SQ2/4;
350
    float G = 1.0f/12;
351

    
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
    float[] vertices1 = { -F,-G, +F,-G, 0,2*G};
366

    
367
    float[] bands1 = { 1.0f   , 0.0f,
368
                       0.5f   , 0.01f,
369
                       0.0f   , 0.01f };
370

    
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
    float d0 =-0.03f;
408
    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

    
470
    mFaceMesh.mergeEffComponents();
471
    }
472

    
473
///////////////////////////////////////////////////////////////////////////////////////////////////
474

    
475
  float getScreenRatio()
476
    {
477
    return 2.0f;
478
    }
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
    int index = QUAT_INDICES[cubit];
533
    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
    return offset<0.125f ? 0:3;
624
    }
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
}
(4-4/14)